2015-01-02 50 views
0

我想弄清楚每個URL顯示在這個哈希多少次。我想最終找到出現次數最多的網址。哈希grouped_by方法迭代通過一個數字作爲一個鍵

urls = [ 
    {'url' => 'yahoo.com/blog'}, 
    {'url' => 'yahoo.com/info'}, 
    {'url' => 'yahoo.com/blog'} 
] 

我有這個至今:

urls.group_by {|hash| hash.values} 

我在哪裏何去何從?

+0

你是從什麼地方接收的散列,或者是你生成它?如果你正在生成它,那麼也許你應該看看這樣做的代碼,而不是打擾做一組哈希,而是做一個簡單的數組。這將簡化問題。 –

+0

哪個哈希?你有幾個哈希。而且似乎每個散列都有一個URL。 – sawa

回答

3

這裏是我見過很多關於陣列中的計數事物的成語:

urls = [{'url' => 'yahoo.com/blog'}, {'url' => 'yahoo.com/info'}, {'url' => 'yahoo.com/blog'}] 

urls.each.with_object(Hash.new(0)) {|url, h| h[url['url']] += 1 } 
#=> {"yahoo.com/blog"=>2, "yahoo.com/info"=>1} 

編輯

如果你堅持要用Hash#group_by,你可以做到這一點,儘管它效率較低:

urls.group_by {|hash| hash.values }.map {|k, v| [k.first, v.length] }.to_h 
+1

你是不是指'each_with_object'? 'each.with_object'很好,只是不尋常的。 –

1

我喜歡用inject與這種事情的累加器:

2.1.2 :011 > urls = [{'url' => 'yahoo.com/blog'}, {'url' => 'yahoo.com/info'}, {'url' => 'yahoo.com/blog'}] 
=> [{"url"=>"yahoo.com/blog"}, {"url"=>"yahoo.com/info"}, {"url"=>"yahoo.com/blog"}] 
2.1.2 :012 > urls.map{ |u| u['url'] }.inject({}){ |acc,url| 
2.1.2 :013 >  acc[url] ||= 0 
2.1.2 :014?> acc[url] += 1 
2.1.2 :015?> acc 
2.1.2 :016?> } 
=> {"yahoo.com/blog"=>2, "yahoo.com/info"=>1} 
+0

雖然,Adrian的答案'each.with_object',有些更優雅 –

+0

恕我直言,最好在塊的返回值改變時使用'inject' - 每次塊中''acc'總是同一個對象運行 – Adrian

1

你可以寫:

urls.flat_map(&:values) 
    .group_by { |u| u } 
    .map { |u,us| [u, us.size ] } 
    .max_by(&:last) 
    #=> ["yahoo.com/blog", 2] 

步驟如下:

a = urls.flat_map(&:values) 
    #=> ["yahoo.com/blog", "yahoo.com/info", "yahoo.com/blog"] 
b = a.group_by { |u| u } 
    #=> {"yahoo.com/blog"=>["yahoo.com/blog", "yahoo.com/blog"], 
    # "yahoo.com/info"=>["yahoo.com/info"]} 
c = b.map { |u,us| [u, us.size ] } 
    #=> [["yahoo.com/blog", 2], ["yahoo.com/info", 1]] 
c.max_by(&:last) 
    #=> ["yahoo.com/blog", 2] 

另一種方式:

urls.each_with_object({}) { |u,h| h.update({ u['url']=>1 }) { |_,o,n| o+n } } 
    .max_by { |_,v| v } 
    # => ["yahoo.com/blog", 2] 
相關問題