.each_with_object红宝石的解释?

时间:2014-10-29 15:50:11

标签: ruby hash

下面,我们将获得一个名为win_lose的数组。我们应该创建一个看起来像下面的哈希的哈希。我最初的倾向是使用.count做一些事情,但在尝试答案之后,.each_with_object工作得最好。

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

谢谢!

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

基于win_lose数组创建一个如下所示的哈希:

 win_loss_count = {
   "win" => 4,
   "loss" => 2
 }

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

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 }

2 个答案:

答案 0 :(得分:5)

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返回“对象”,因此会返回{{1}},并为每个单词进行修改。

答案 1 :(得分:2)

Nick完全正确,实际上有其他方法可以将对象传递到块中以帮助您,但是您的结构需要输出。您将在ruby中看到的最常见的一种是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}

我们正在做同样的事情,我们发送的哈希值默认值为零,我们正在构建每次迭代的新哈希。