2015-10-08 97 views
0

我有两个散列:红宝石 - 合并两个散列,并保持有序的按键

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) 

是否有一个内置的红宝石方法或工具,它可以实现一个更清洁的方式完成相同的任务?

+5

这是一个非常古怪的数据结构。为什么不使用数组呢?字符串索引看起来完全是任意的,并且将会是一种难以分类的痛苦。例如,如果它们是字符串,则为“0,1,10,2”。 – tadman

+0

有没有这样的事情,有序的哈希。 – Mircea

+3

@Mircea,我相信Ruby 1.9添加了有序哈希,它保留了插入顺序。 –

回答

2
(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"} 
+2

代码非常密集的块。可以变成一个通用函数,它使用N个参数,如:def crunch(* hashes)和hashes.collect(&:values).inject(:+).uniq'来计算重叠。 – tadman

1

首先创建一个包含散列值的数组。这可以通过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"} 
1
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"}