Создайте пересечение двух значений ключа, если ключи в 2 отдельных хешах равны. Рубин - PullRequest
1 голос
/ 24 ноября 2010

Я пытаюсь создать пересечение значений 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, кстати.

Я знаю, что массивы можно пересекать с помощью «&» и «set», хотя я не смог этого сделать вмой сценарий до сих пор.

Любой совет будет отличным.Спасибо.

Для Тео:

Да.
hash1 {alpha: [a, b, c, d, e], браво: [f, g, h, i, j], Чарли: [k, l, m, n, o], дельта: [p, r]}

hash2 {alpha: [a, c, q, z], браво: [z, x], Чарли: [k, l, m, n]}

Итак, пересечение будет выглядеть так.

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

Ответы [ 4 ]

1 голос
/ 24 ноября 2010

Для регулярного пересечения двух хешей:

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 не является общим элементом между :bravoвведите hash1 и hash2, чтобы это не имело смысла.Если вам нужен пустой список для ключей, которые находятся в hash1 и hash2, но не имеют общих элементов в их списках значений, вы можете удалить третью строку, которая в противном случае удалит их.

0 голосов
/ 25 ноября 2010
def merge_hash(hash1, hash2)
  result = {}

  hash1.keys.each do |k|
    result[k] = hash1[k] & hash2[k] unless hash2[k].nil?
  end
  result
end
0 голосов
/ 25 ноября 2010
Hash[h2.collect { |k,v| h1[k] ? [k, h1[k] & h2[k]] : [] }]

Кроме того, сначала вы проверяете размер h1.keys по сравнению с h2.keys, а затем перебираете меньший.Он теряет немного ясности из вышеперечисленного, но он будет работать намного лучше для больших хэшей с несоответствием размеров.

0 голосов
/ 24 ноября 2010
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] }
...