Ruby:map和inject的区别

5

在Stack Overflow上阅读各种说明后,它们被描述如下:


Map(映射):

Map方法接受一个可枚举对象和一个块,并针对每个元素运行该块


Inject(注入):

Inject方法需要一个值和一个块,对列表中的每个元素运行该块。

希望您理解为什么我觉得它们在表面上看起来非常相似。在何时应选择其中之一?它们之间是否有明显的区别?


11
你尝试过阅读 mapinject 的官方文档吗? - toro2k
6
我认为这些负评并不合理。SO愿意重复即使是最基本的核心语言文档,只要之前在SO上没有被问到过。通常,各种回答会使用不同的措辞来解释相同的事情,即使在思想方面没有添加任何新内容。有时,这对于直观理解概念非常有帮助。此外,在SO上的回答中,我曾经因为一些我认为简单和无聊的问题出现了意想不到的细微差别。所以,确保先看完文档,但如果之前没有在SO上询问过,那就来SO提问。 - labyrinth
3个回答

12

如果你考虑到inject也被别名为reduce,会更有帮助。map用于转换列表,例如将数组中的所有字符串转换为大写,而inject则使用一个参数(通常是累加器)并对其进行修改。

示例:

 %w(a b c).map(&:upcase) #=> ["A", "B", "C"]
 [*1..4].inject(:+) #=> 10

如果您想阅读更多内容,inject 的作用被称为fold


1
你的表述让这些概念更易理解了。谢谢! - krystah
对于本质上是聚合函数的东西,我发现使用(1..4).sum #=> 10更易读和直观。 - nroose
1
@nroose 这个问题没有标记为Rails。在纯Ruby中,(1..4).sum #=> NoMethodError: undefined method sum' for 1..4:Range`。 - Michael Kohl

4

inject 接收一个对象作为参数,对其进行一些操作并返回修改后的对象。

arr = []
[1,2].inject(arr) { |s,e| s << e }
arr # => [1,2]

在上面的例子中,我传递了一个空数组arr,但在调用#inject后,在块内进行了concatenation操作,并将其添加到arr中。之后我打印出它,我可以看到arr现在包含条目,它们是1,2map创建一个新的Enumerable对象,该对象基于您调用它的接收器Enumerable对象创建。它将从接收器中获取每个元素,并执行一些操作,然后将其放入新的可枚举元素中,然后继续进行下一个操作,以此类推...
arr = [1,2]
arr.map { |e| e + 1 } # => [2,3]
arr # => [1,2]

使用#map,块将每个参数逐个加1,然后将递增的值放在新数组中与原始元素取自相同的索引处。但是,最终的数组是一个全新的数组,与arr没有任何关联。当我执行p arr时,我得到的是在#map操作开始之前arr中具有相同内容的结果。

3
使用inject时,通常会返回一个值(通常用于数学),而使用map时会返回一个数组。

1
尽管人们经常看到 a.inject([])({}) - Cary Swoveland
我发现inject非常令人困惑,而map则更直观。如果您只是对某些内容进行求和,则使用each或数组上的聚合函数即可得出结果。 - nroose

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接