2013-03-22 27 views
1

那個鍵我有一個數組哈希表中的紅寶石作爲值的數量合併的鍵值對:最好的方法在哈希基礎上使用Ruby

@people = { "a" => ["john", "mark", "tony"], "b"=> ["tom","tim"], 
      "c" =>["jane"], "others"=>["rob", "ryan"] } 

我想合併所有鍵值對,其中對於特定的鍵值,數組中少於3個項目。他們應該合併到一個名爲「其他」的關鍵,給予大致的

@people = { "a" => ["john", "mark", "tony"], 
      "others"=> ["rob", "ryan", "tom", "tim", "jane"] } 

結果使用下面的代碼是問題,因爲在哈希重複的鍵值就不能存在:

@people = Hash[@people.map{|k,v| v.count<3 ? ["others",v] : [k,v]} ] %> 

最新最好的優雅地解決這個問題的方法?

回答

2

你幾乎擁有它,問題是,正如你注意到的那樣,由於重複,你無法即時創建哈希鍵/值對。解決該問題的方法之一是與你想建什麼骨架開始了:

@people = @people.each_with_object({ 'others' => [ ] }) do |(k,v), h| 
    if(v.length >= 3) 
     h[k] = v 
    else 
     h['others'] += v 
    end 
end 

或者,如果你不喜歡each_with_object,你可以:

h = { 'others' => [ ] } 
@people.each do |k, v| 
    # as above 
end 
@people = h 

或者你可以使用與inject幾乎相同的結構(像往常一樣照顧,從塊中返回正確的東西)。

當然有其他方法可以做到這一點,但這些方法非常清晰易懂; IMO的清晰度應該是你的第一個目標。

+0

首先感謝解決方案each_with_object運作良好,解決了它!非常感謝 – 2013-03-22 16:45:31

+0

有趣的是,這項工作在開發中,但沒有投入生產時 - 任何想法? – 2013-03-23 17:29:36

+0

你確定你在生產中有長度大於3的陣列嗎? – 2013-03-23 18:53:33

0

這個怎麼樣:

> less_than_three, others = @people.partition {|(key, values)| values.size >= 3 } 
> Hash[less_than_three] 
# => {"a"=>["john", "mark", "tony"]} 
> Hash["others" => others.map {|o| o.last}.flatten] 
# => {"others"=>["tom", "tim", "jane", "rob", "ryan"]} 
0
@people[:others] = [] 
@people.each do |k, v| 
    @people[:others] |= @people.delete(k) if v.size < 3 
end 
0
@people.inject({}) do |m, (k, v)| 
    m[i = v.size >= 3 ? k : 'others'] = m[i].to_a + v 
    m 
end 
+0

你可以使用'each_with_object'移除一條線, – oldergod 2013-03-22 04:53:18

1

嘗試:用

>> @people = { "a" => ["john", "mark", "tony"], "b"=> ["tom","tim"], 
     "c" =>["jane"], "others"=>["rob", "ryan"] } 

>> @new_people = {"others" => []} 

>> @people.each_pair {|k,v| (v.size >= 3 && k!="others") ? @new_people.merge!(k=>v) : @new_people['others']+= v}  

>> @new_people 
=> {"others"=>["rob", "ryan", "jane", "tom", "tim"], "a"=>["john", "mark", "tony"]} 
+0

謝謝這也行! – 2013-03-22 16:58:49

+0

這工作在生產中謝謝你 – 2013-03-23 17:48:35

1
Hash[ @people.group_by { |k,v| v.size < 3 ? 'others' : k }. 
       map { |k,v| [k, v.flat_map(&:last)] } ] 

=> {"a"=>["john", "mark", "tony"], 
    "others"=>["tom", "tim", "jane", "rob", "ryan"]}