根据 Ruby 中的唯一散列键比较数组及其内部散列的最有效方法
Most efficient way of comparing arrays with hashes inside them based on a unique hash key in Ruby
我有两个散列 hash_a 和 hash_b,它们实际上是数组,但里面有散列。这些散列具有唯一键。
hash_a = [
{:unique_key => 1, :data => 'data for A1'},
{:unique_key => 2, :data => 'data for A2'},
{:unique_key => 3, :data => 'data for A3'}
]
hash_b = [
{:unique_key => 1, :data => 'data for B1'},
{:unique_key => 2, :data => 'data for B2'},
{:unique_key => 4, :data => 'data for B4'},
{:unique_key => 5, :data => 'data for B5'}
]
现在我想找出 hash_a 和 hash_b 之间的区别,这样我就可以得到 hash_c 作为 hash_b 中存在的新哈希数组。
我基本上想要hash_b - hash_a
所以我想要 hash_c 的输出,hash_c 应该是这样的:
[
{:unique_key => 1, :data => 'data for A1'},
{:unique_key => 2, :data => 'data for A2'},
{:unique_key => 3, :data => 'data for A3'},
{:unique_key => 4, :data => 'data for B4'},
{:unique_key => 5, :data => 'data for B5'}
]
我试过这样的方法:
hash_c = hash_a
hash_b.each do |inner_bhash|
found = 0
hash_a.each do |inner_ahash|
if(inner_ahash[:unique_key] == inner_bhash[:unique_key])
found = 1
break
end
end
if(found==0)
hash_c.push(inner_bhash)
end
end
这是解决问题的方法,但我想要一个更好的方法。比如hashmap什么的,我也不知道。
此外,我可能只想查看新条目,即
[
{:unique_key => 4, :data => 'data for B4'},
{:unique_key => 5, :data => 'data for B5'}
]
我可以通过替换
在我的代码中做到这一点
hash_c = hash_a
和
hash_c = []
但我如何才能以同样的方式调整此要求?
使用 Hash
es 你可以使用 merge
做你想做的事 - 所以通过将每个 Array
变成 Hash
你可以做以下事情:
hash_b.group_by { |e| e[:unique_key] }.
merge(hash_a.group_by { |e| e[:unique_key] }).values.flatten
# => [{:unique_key=>1, :data=>"data for A1"},
# {:unique_key=>2, :data=>"data for A2"},
# {:unique_key=>4, :data=>"data for B4"},
# {:unique_key=>5, :data=>"data for B5"},
# {:unique_key=>3, :data=>"data for A3"}]
如果你只想拥有 hash_b
的条目(在 hash_a
中没有键),假设你已经有了上面的解决方案 - 你可以简单地 从结果中减去 hash_a
:
hash_b.group_by { |e| e[:unique_key] }.
merge(hash_a.group_by { |e| e[:unique_key] }).values.flatten - hash_a
# => [{:unique_key=>4, :data=>"data for B4"},
# {:unique_key=>5, :data=>"data for B5"}]
另一种更直接的方法是过滤掉 hash_b
中所有在 hash_a
中有条目的元素:
hash_b.select { |x| hash_a.none? { |y| x[:unique_key] == y[:unique_key] } }
# => [{:unique_key=>4, :data=>"data for B4"},
# {:unique_key=>5, :data=>"data for B5"}]
您可以使用 Array#uniq 的形式来占用一个块。
(hash_a + hash_b).uniq { |h| h[:unique_key] }
#=> [{:unique_key=>1, :data=>"data for A1"}, {:unique_key=>2, :data=>"data for A2"},
# {:unique_key=>3, :data=>"data for A3"}, {:unique_key=>4, :data=>"data for B4"},
# {:unique_key=>5, :data=>"data for B5"}]
引用文档,"self is traversed in order, and the first occurrence is kept."
我有两个散列 hash_a 和 hash_b,它们实际上是数组,但里面有散列。这些散列具有唯一键。
hash_a = [
{:unique_key => 1, :data => 'data for A1'},
{:unique_key => 2, :data => 'data for A2'},
{:unique_key => 3, :data => 'data for A3'}
]
hash_b = [
{:unique_key => 1, :data => 'data for B1'},
{:unique_key => 2, :data => 'data for B2'},
{:unique_key => 4, :data => 'data for B4'},
{:unique_key => 5, :data => 'data for B5'}
]
现在我想找出 hash_a 和 hash_b 之间的区别,这样我就可以得到 hash_c 作为 hash_b 中存在的新哈希数组。
我基本上想要hash_b - hash_a
所以我想要 hash_c 的输出,hash_c 应该是这样的:
[
{:unique_key => 1, :data => 'data for A1'},
{:unique_key => 2, :data => 'data for A2'},
{:unique_key => 3, :data => 'data for A3'},
{:unique_key => 4, :data => 'data for B4'},
{:unique_key => 5, :data => 'data for B5'}
]
我试过这样的方法:
hash_c = hash_a
hash_b.each do |inner_bhash|
found = 0
hash_a.each do |inner_ahash|
if(inner_ahash[:unique_key] == inner_bhash[:unique_key])
found = 1
break
end
end
if(found==0)
hash_c.push(inner_bhash)
end
end
这是解决问题的方法,但我想要一个更好的方法。比如hashmap什么的,我也不知道。
此外,我可能只想查看新条目,即
[
{:unique_key => 4, :data => 'data for B4'},
{:unique_key => 5, :data => 'data for B5'}
]
我可以通过替换
在我的代码中做到这一点hash_c = hash_a
和
hash_c = []
但我如何才能以同样的方式调整此要求?
使用 Hash
es 你可以使用 merge
做你想做的事 - 所以通过将每个 Array
变成 Hash
你可以做以下事情:
hash_b.group_by { |e| e[:unique_key] }.
merge(hash_a.group_by { |e| e[:unique_key] }).values.flatten
# => [{:unique_key=>1, :data=>"data for A1"},
# {:unique_key=>2, :data=>"data for A2"},
# {:unique_key=>4, :data=>"data for B4"},
# {:unique_key=>5, :data=>"data for B5"},
# {:unique_key=>3, :data=>"data for A3"}]
如果你只想拥有 hash_b
的条目(在 hash_a
中没有键),假设你已经有了上面的解决方案 - 你可以简单地 从结果中减去 hash_a
:
hash_b.group_by { |e| e[:unique_key] }.
merge(hash_a.group_by { |e| e[:unique_key] }).values.flatten - hash_a
# => [{:unique_key=>4, :data=>"data for B4"},
# {:unique_key=>5, :data=>"data for B5"}]
另一种更直接的方法是过滤掉 hash_b
中所有在 hash_a
中有条目的元素:
hash_b.select { |x| hash_a.none? { |y| x[:unique_key] == y[:unique_key] } }
# => [{:unique_key=>4, :data=>"data for B4"},
# {:unique_key=>5, :data=>"data for B5"}]
您可以使用 Array#uniq 的形式来占用一个块。
(hash_a + hash_b).uniq { |h| h[:unique_key] }
#=> [{:unique_key=>1, :data=>"data for A1"}, {:unique_key=>2, :data=>"data for A2"},
# {:unique_key=>3, :data=>"data for A3"}, {:unique_key=>4, :data=>"data for B4"},
# {:unique_key=>5, :data=>"data for B5"}]
引用文档,"self is traversed in order, and the first occurrence is kept."