2012-06-08 39 views
5

我有一个简单的数组将元组的Ruby元组转换为散列给定的一组键?

array = ["apple", "orange", "lemon"] 

array2 = [["apple", "good taste", "red"], ["orange", "bad taste", "orange"], ["lemon" , "no taste", "yellow"]] 

我怎样才能转换到该散列每当在数组元素中数组2的每个元件的第一元件相匹配?

hash = {"apple" => ["apple" ,"good taste", "red"], 
     "orange" => ["orange", "bad taste", "orange"], 
     "lemon" => ["lemon" , "no taste", "yellow"] } 

我对红宝石颇为陌生,花了很多钱做这个操作,但没有运气,有什么帮助?

+0

那你究竟是“符合每个元素的数组2的第一个元素”是什么意思? – Mischa

+4

不要编辑我的答案,发表评论 – Mischa

回答

10

如果密钥与对之间的映射的顺序,应根据在array2的第一个元素,那么你不需要array都:

array2 = [ 
    ["apple", "good taste", "red"], 
    ["lemon" , "no taste", "yellow"], 
    ["orange", "bad taste", "orange"] 
] 

map = Hash[ array2.map{ |a| [a.first,a] } ] 
p map 
#=> { 
#=> "apple"=>["apple", "good taste", "red"], 
#=> "lemon"=>["lemon", "no taste", "yellow"], 
#=> "orange"=>["orange", "bad taste", "orange"] 
#=> } 

如果你想使用array选择元素的子集,那么你可以这样做:

# Use the map created above to find values efficiently 
array = %w[orange lemon] 
hash = Hash[ array.map{ |val| [val,map[val]] if map.key?(val) }.compact ] 
p hash 
#=> { 
#=> "orange"=>["orange", "bad taste", "orange"], 
#=> "lemon"=>["lemon", "no taste", "yellow"] 
#=> } 

代码if map.key?(val)compact确保如果array要求在array2中不存在的密钥,并且在O(n)时间中这样做,则没有问题。

+0

这没有考虑到以下要求:“只要数组中的元素匹配数组2中每个元素的第一个元素”。 – Mischa

+0

@Mischa它现在。 :) – Phrogz

2

这会让您获得理想的结果。

hash = {} 

array.each do |element| 
    i = array2.index{ |x| x[0] == element } 
    hash[element] = array2[i] unless i.nil? 
end 
+0

嗨,thx,如果array2没有按顺序呢? –

+1

那么这不是你的问题。下一次更清楚地反映出你想要的例子。 'array'中'''',''''''和''''可以出现多次,如果是这样的话,你希望看到结果散列。请用一个明确的例子和期望的输出来更新你的问题。 – Mischa

+0

@KitHo,这个工作如果数组不正确。 – Mischa

-1

ohh..I诱惑覆盖rassoc

退房以下IRB

class Array 
    def rassoc obj, place=1 
    if place 
     place = place.to_i rescue -1 
     return if place < 0 
    end 

    self.each do |item| 
     next unless item.respond_to? :include? 

     if place 
     return item if item[place]==obj 
     else 
     return item if item.include? obj 
     end 
    end 

    nil 
    end 
end 

array = ["apple", "orange", "lemon"] 
array2 = [["apple", "good taste", "red"], ["orange", "bad taste", "orange"], ["lemon" , "no taste", "yellow"]] 

Hash[ array.map{ |fruit| [fruit, array2.rassoc(fruit, nil)]}] 
# this is what you want 

# order changed 
array2 = [["good taste", "red", "apple"], ["no taste", "lemon", "yellow"], ["orange", "bad taste", "orange"]] 

Hash[ array.map{ |fruit| [fruit, array2.rassoc(fruit, nil)]}] 
# same what you want after order is changed