Ruby - 合并两个散列并维护有序键

Ruby - Merge two hashes and maintain ordered keys

我有两个哈希:

a = {"0"=>"name", "1"=>"email"} 
b = {"0"=>"source", "1"=>"info", "2"=>"extra", "3"=>"name"} 

我想要通过执行以下操作创建的哈希:

1) 当两个哈希包含相同的值时,保留原始哈希的值并丢弃第二个哈希的值。

2) 当第二个哈希的值不在第一个哈希中时,只需添加到新哈希的末尾,确保键是有序的。

结果为:

{"0"=>"name", "1"=>"email", "2"=>"source", "3"=>"info", "4"=>"extra"}

我这样做很丑陋:

l1 = a.keys.length
l2 = b.keys.length
max = l1 > l2 ? l1 : l2
counter = l1
result = {}
max.times do |i|
  unless a.values.include? b[i.to_s]
    result[counter.to_s] = b[i.to_s]
    counter += 1
  end
end
a.merge!(result)

是否有内置的 ruby 方法或实用程序可以更简洁地完成同样的任务?

(a.values + b.values).uniq.map.with_index{|v, i| [i.to_s, v]}.to_h
# => {"0"=>"name", "1"=>"email", "2"=>"source", "3"=>"info", "4"=>"extra"}

首先创建一个包含哈希值的数组。这可以通过 concat 方法来完成。现在我们有了一个数组,我们可以调用 uniq 方法来检索所有唯一值。这也保留了顺序。

a = { "0" => "name", "1" => "email" }
b = { "0" => "source", "1" => "info", "2" => "extra", "3" => "name" }
values = a.values.concat(b.values).uniq

在 Ruby 中生成哈希的捷径就是这个技巧。

Hash[[*0..values.length-1].zip(values)]

输出:

{0=>"name", 1=>"email", 2=>"source", 3=>"info", 4=>"extra"}
a = {"0"=>"name", "1"=>"email"} 
b = {"0"=>"source", "1"=>"info", "2"=>"extra", "3"=>"name"} 

key = (a.size-1).to_s
  #=> "1"
b.each_value.with_object(a) { |v,h| (h[key.next!] = v) unless h.value?(v) }
  #=> {"0"=>"name", "1"=>"email", "2"=>"source", "3"=>"info", "4"=>"extra"}