2012-06-08 38 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