如果两个独立哈希中的键相等,则创建两个键值的交集。红宝石

时间:2010-11-24 18:45:23

标签: ruby arrays hash intersection

我正在尝试创建hash1的值与hash2的值的交集,如果这些值共享相同的键。到目前为止,这是我的代码。我能够生成两个哈希 - >数据和数据1。

#!/usr/bin/env ruby

require 'pp'
require 'set'
data = {}
File.read(ARGV[0]).each do |l|
  l.chomp!
  key, value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12 = l.split(/\s+/)
  data[key] ||= {}
  values = [value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12]
  data[key] = values.compact!

end

data1 = {}
File.read(ARGV[1]).each do |l|
  l.chomp!
  value = l.split(/\s+/)
  data1[value[0]] ||= {}
  data1[value[0]] = [value] 
end

因此,我的主要目标是hash1中的每个键,只保留hash2中相同键所存在的那些值,否则从hash1中删除这些值。我并不关心Hash2中存在的任何密钥,这些密钥在Hash1,btw中不存在。

我知道阵列可以使用“&”进行交叉并且“设定”,但到目前为止我还没有在我的剧本中完成这个。

任何建议都会很棒。感谢。

对于Theo:

是。
hash1 {alpha:[a,b,c,d,e],bravo:[f,g,h,i,j],charlie:[k,l,m,n,o],delta:[p,r ]}

hash2 {alpha:[a,c,q,z],bravo:[z,x],charlie:[k,l,m,n]}

所以,交叉点看起来像这样。

hash3 {alpha:[a,c],bravo:[nil],charlie:[k,l,m,n]}

4 个答案:

答案 0 :(得分:1)

对于两个哈希的常规交集:

Hash[h1.to_a & h2.to_a]

但你的情况有点不同。您可以使用以下代码获取您正在寻找的交叉路口:

hash1 = {:alpha => [:a,:b,:c,:d,:e], :bravo => [:f,:g,:h,:i,:j], :charlie => [:k,:l,:m,:n,:o], :delta => [:p,:r]}
hash2 = {:alpha => [:a,:c,:q,:z], :bravo => [:z,:x], :charlie => [:k,:l,:m,:n]}

common_keys = hash1.keys & hash2.keys 
  # => [:alpha, :bravo, :charlie]
intersection = common_keys.map { |k| [k, hash1[k] & hash2[k]] } 
  # => [[:alpha, [:a, :c]], [:bravo, []], [:charlie, [:k, :l, :m, :n]]]
intersection = intersection.reject { |k, v| v.empty? } 
  # => [[:alpha, [:a, :c]], [:charlie, [:k, :l, :m, :n]]]
Hash[intersection]
  # => {:alpha=>[:a, :c], :charlie=>[:k, :l, :m, :n]}

您的示例包含:bravo => [nil],但我认为这是一个错误,因为nil不是:bravohash1hash2键之间的常见元素,所以没有意义。如果您想要hash1hash2中的键的空列表,但其值列表中没有公共元素,则可以删除第三行,否则会删除第三行。

答案 1 :(得分:0)

data  = { a: [11], b: [22, 222], c: [33] }
data2 = { b: [222, 2222], d: [4444] }

Hash[data.map {|k, v| if data2[k] then [k, v & data2[k]] end }.compact]
# => { b: [222] }

答案 2 :(得分:0)

Hash[h2.collect { |k,v| h1[k] ? [k, h1[k] & h2[k]] : [] }]

此外,首先检查h1.keys的大小与h2.keys的比较,然后首先迭代较小的一个。它失去了上面的清晰度,但对于尺寸不一致的较大哈希,它会表现得更好。

答案 3 :(得分:0)

def merge_hash(hash1, hash2)
  result = {}

  hash1.keys.each do |k|
    result[k] = hash1[k] & hash2[k] unless hash2[k].nil?
  end
  result
end