如何修改具有重复属性的数组中的对象?(XY 坐标)



我有一个带有XY坐标的对象(节点(数组。无论我在哪里找到覆盖另一个节点的节点(具有完全相同的 XY 坐标(,我都想将 Y 属性"up"编辑 3。

id,x,y都是我正在查看的对象的属性。并集体保存在节点数组中。

我希望遍历数组,每当存在重复的 XY 时,通过在 Y 属性中添加 3 来编辑第一个非唯一实例。如果找到另一个重复项,我希望将此对象的 Y 属性更改为 6,依此类推。

例如


NODE      X        Y
node1   267555   666777   
node2   267555   666777
node3   245698   656400
node4   267555   666777

我希望节点 2 和节点 4 变成:

NODE      X        Y
node1   267555   666777   
node2   267555   666780
node3   245698   656400
node4   267555   666783

本质上,对于重复 XY 的每个实例,将 3 添加到"Y",并且对于数组中存在覆盖节点的每个实例(实际数组要大得多(。

我已经设法使用识别重复项,但不确定如何进行:

duplicates = nodes.group_by{|i| [i.x, i.y] }.select{|k,v| v.length > 1}.values

但是我不想要一个新数组,我希望修改原始的"节点"数组属性。

谢谢

让我们从创建一个节点类开始。

class Nodes
attr_accessor :name, :x, :y
def initialize(name, x, y)
@name = name
@x = x
@y = y
end
end

接下来,创建问题中显示的实例。

nodes = [
Nodes.new("node1", 267555, 666777),
Nodes.new("node2", 267555, 666777),
Nodes.new("node3", 245698, 656400),
Nodes.new("node4", 267555, 666777)
]
#=> [#<Nodes:0x00005c7949ee8e40 @name="node1", @x=267555, @y=666777>,
#    #<Nodes:0x00005c7949f57c50 @name="node2", @x=267555, @y=666777>,
#    #<Nodes:0x00005c7949f57958 @name="node3", @x=245698, @y=656400>,
#    #<Nodes:0x00005c7949f577a0 @name="node4", @x=267555, @y=666777>] 

现在根据需要修改y值。为此,我们使用方法Hash::new的形式,该方法采用称为默认值的参数。如果以这种方式创建了哈希h,则h[k]如果没有键k,它将返回默认值。这有时称为计数哈希

nodes.each_with_object(Hash.new(0)) do |inst,h|
y = inst.y
inst.y += 3 * h[y] if h.key?(y) 
h[y] += 1
end
#=> {666777=>3, 656400=>1} 

让我们看看nodes现在的样子。

nodes
#=> [#<Nodes:0x00005c7949ee8e40 @name="node1", @x=267555, @y=666777>,
#    #<Nodes:0x00005c7949f57c50 @name="node2", @x=267555, @y=666780>,
#    #<Nodes:0x00005c7949f57958 @name="node3", @x=245698, @y=656400>,
#    #<Nodes:0x00005c7949f577a0 @name="node4", @x=267555, @y=666783>] 
nodes.map { |inst| [inst.name, inst.x, inst.y] }
#=> [["node1", 267555, 666777],
#    ["node2", 267555, 666780],
#    ["node3", 245698, 656400],
#    ["node4", 267555, 666783]]