.each_with_object ruby​​解释?

问题描述:

下面我们给出一个名为win_lose的数组。我们应该创建一个哈希,看起来像下面的哈希。我最初的意图是使用.count来做某些事情,但在尝试回答之后,.each_with_object工作得最好。.each_with_object ruby​​解释?

有人可以为我分解什么.each_with_object方法正在做的和答案本身?我得到了答案,并从阅读文档中找出它,但仍然需要解释方法本身...

谢谢!

win_lose = ["win", "lose", "win", "lose", "win", "win"] 

创建基于win_lose阵列上的哈希,看起来像这样:

这是我最初尝试没有成功:

win_loss_count = Hash[win_lose.map.with_index { |outcome, times| outcome = times.count }] 

答:

win_loss_count = win_lose.each_with_object(Hash.new(0)) { |word,counts| counts[word] += 1 } 

each_with_object的字面意思就是它所说的。这就像each,但每次都有一个额外的对象。

因此,对于这个:

win_lose.each_with_object(Hash.new(0)) { |word,counts| counts[word] += 1 } 

你打电话each,与对象通过Hash.new(0)传入为好,每次创建。 word是你在正常的each中得到的单词,而counts是被称为“with_object”的对象(所以,哈希)。

重要的是这个快捷方式是Hash.new(0)。这意味着创建一个新的空散列,其中0表示所有以前不存在的键的值,即使它以前不存在,也可以执行counts[word] += 1

最后,each_with_object返回“对象”,所以返回counts,对每个单词都进行了修改。

+2

谢谢尼克这个彻底的解释。我现在明白它好多了! – user3604867 2014-10-29 17:03:56

尼克有它完全正确的,事实上有其他方法可以传递对象到一个块来帮助你,但是你的结构需要输出。在红宝石中最常见的一种方法是Enumerable#inject方法。你同样的答案可以写成像

win_lose.inject(Hash.new(0)) { |hash, val| hash[val] += 1; hash } 

执行相同的操作:

[14] pry(main)> win_lose 
=> ["win", "lose", "win", "lose", "win", "win"] 
[15] pry(main)> win_lose.inject(Hash.new(0)) { |hash, val| hash[val] += 1; hash } 
=> {"win"=>4, "lose"=>2} 

我们正在做同样的事情,我们在哈希谁的默认值要发送到零到块,我们正在每次迭代构建新的散列。

+1

谢谢安东尼!使用.inject是非常有用的。感谢您将我的注意力引入并解释! – user3604867 2014-10-29 17:03:35

+0

安东尼 - 问题 - 在这个部分:win_lose.inject(Hash.new(0)){| type,num |键入[num] + = 1;类型} ...如果我没有写分号和类型(或像上面那样的散列),我得到这个错误:“没有将字符串隐式转换为整数”。这是为什么? – user3604867 2014-10-29 17:40:28

+0

当然,您必须将散列返回到块中,这就是分号正在做的事情。同时,我们实例化Hash.new(0),它修复了您引用的字符串 - >整数问题。 – Anthony 2014-10-29 17:48:23