#each_with_object和#inject都可用于构建哈希值。
例如:
matrix = [['foo', 'bar'], ['cat', 'dog']]
some_hash = matrix.inject({}) do |memo, arr|
memo[arr[0]] = arr
memo # no implicit conversion of String into Integer (TypeError) if commented out
end
p some_hash # {"foo"=>["foo", "bar"], "cat"=>["cat", "dog"]}
another_hash = matrix.each_with_object({}) do |arr, memo|
memo[arr[0]] = arr
end
p another_hash # {"foo"=>["foo", "bar"], "cat"=>["cat", "dog"]}
两者之间的主要区别之一是#each_with_object
在整个迭代过程中跟踪memo
,而#inject
设置memo
等于块上返回的值每次迭代。
另一个区别是顺序或块参数。
这里是否有意向传达?反转两种类似方法的块参数没有意义。
答案 0 :(得分:7)
他们有不同的血统。
each_with_object
已添加到2007年的Ruby 1.9 inject
可追溯到1980年的Smalltalk 我想如果语言是从开头设计的两种方法,他们可能会期望相同顺序的参数。但事实并非如此。自{Ruby'开始以来inject
已经存在,而each_with_object
仅在10年后被添加。
inject
期望参数的顺序与Smalltalk的inject:into:
collection inject: 0 into: [ :memo :each | memo + each ]
左侧折叠。您可以将该集合视为从左侧折叠起来的长条纸,折叠功能的滑动窗口始终是已折叠的部分以及剩余纸条的下一个元素
# (memo = 0 and 1), 2, 3, 4
# (memo = 1 and 2), 3, 4
# (memo = 3 and 3), 4
# (memo = 6 and 4)
由于Smalltalk约定在当时有意义,因为Enumerable
中的所有初始方法都来自Smalltalk,Matz不想混淆熟悉Smalltalk的人。
也许没有人有远见知道会在2007年将each_with_object
引入Ruby 1.9时发生,并且参数的顺序反映了方法名称的词法顺序,即each ... object
。
因此,由于历史原因,这两种方法会以不同的顺序期望参数。