如何从两个哈希数组中获得联合/相交/差异并忽略一些键

Set*_*ack 7 ruby arrays hash union intersect

我想从两个哈希数组中得到union/intersect/difference,例如:

array1 = [{:name =>'Guy1', :age => 45},{:name =>'Guy2', :age => 45}]
array2 = [{:name =>'Guy1', :age => 45},{:name =>'Guy3', :age => 45}]
Run Code Online (Sandbox Code Playgroud)

...

p array1 - array2 

=> [{:name=>"Guy2", :age=>45}]


p array2 - array1
=> [{:name=>"Guy3", :age=>45}]


p array1 | array2 
=> [{:name=>"Guy1", :age=>45}, {:name=>"Guy2", :age=>45}, {:name=>"Guy3", :age=>45}]
Run Code Online (Sandbox Code Playgroud)

但是,当我只想根据名称进行比较并忽略年龄而不需要从哈希中删除它们时,例如:

array1 = [{:name =>'Guy1', :age => 45},{:name =>'Guy2', :age => 45}]
array2 = [{:name =>'Guy1', :age => 46},{:name =>'Guy3', :age => 45}]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我没有得到我想要的结果b/c年龄不同.

array1 - array2 

=> [{:name=>"Guy1", :age=>45}, {:name=>"Guy2", :age=>45}]

array2 - array1
=> [{:name=>"Guy1", :age=>46}, {:name=>"Guy3", :age=>45}]

array1 | array2 
=> [{:name=>"Guy1", :age=>45}, {:name=>"Guy2", :age=>45}, {:name=>"Guy1", :age=>46}, {:name=>"Guy3", :age=>45}]
Run Code Online (Sandbox Code Playgroud)

有没有办法获得联合/交叉/差异并忽略年龄密钥?

编辑:更好的例子:

array1 = [{:name =>'Guy1', :age => 45},{:name =>'Guy2', :age => 45}]
array2 = [{:name =>'Guy1'},{:name =>'Guy3'}]

p array1 - array2
p array2 - array1
p array1 | array2
p array1 & array2
Run Code Online (Sandbox Code Playgroud)

在此先感谢您的帮助!

Mar*_*mas 6

这是获得联盟的快速而肮脏的方式:

(array1 + array2).uniq{|a| a[:name]}
Run Code Online (Sandbox Code Playgroud)

但是,我建议你创建自己的子类,Hash这样你就可以安全地覆盖,eql?因为Cary Swoveland指出了类似于集合的运算符所依赖的东西.请注意,您还需要将hash方法限制为仅在名称字段上提供散列函数.

class Guy < Hash

  def eql?(other_hash)
    self[:name] == other_hash[:name]
  end

  def hash
    self[:name].hash
  end

end
Run Code Online (Sandbox Code Playgroud)

然后这些Guy对象将在所有设置操作中起作用:

array1 = [ Guy[name:'Guy1', age: 45], Guy[name:'Guy2', age: 45] ]
array2 = [ Guy[name:'Guy1', age: 46], Guy[name:'Guy3', age: 45] ]

array1 - array2
#=> [{:name=>"Guy2", :age=>45}]

array2 - array1
#=> [{:name=>"Guy3", :age=>45}]

array1 | array2
#=> [{:name=>"Guy1", :age=>45}, {:name=>"Guy2", :age=>45}, {:name=>"Guy3", :age=>
45}]

array1 & array2
#=> [{:name=>"Guy1", :age=>45}]
Run Code Online (Sandbox Code Playgroud)