Ruby注入初始为哈希

Can*_*ide 48 ruby

可以任何人告诉我为什么以下:

['a', 'b'].inject({}) {|m,e| m[e] = e }
Run Code Online (Sandbox Code Playgroud)

抛出错误:

IndexError: string not matched
        from (irb):11:in `[]='
        from (irb):11:in `block in irb_binding'
        from (irb):11:in `each'
        from (irb):11:in `inject'
        from (irb):11
        from C:/Ruby192/bin/irb:12:in `<main>'
Run Code Online (Sandbox Code Playgroud)

而以下工作?

a = {}
a["str"] = "str"
Run Code Online (Sandbox Code Playgroud)

Rob*_*vis 73

您的块需要返回累积哈希:

['a', 'b'].inject({}) {|m,e| m[e] = e; m }
Run Code Online (Sandbox Code Playgroud)

相反,它在第一次传递后返回字符串'a',这将m在下一次传递中变为最终调用字符串的[]=方法.

  • @Ziggy:是的,这是必要的,因为赋值`hash [key] = value`返回`value`,你需要`hash`. (9认同)
  • 绝对有必要在最后包含 m 吗?例如,如果块是`{ |array, (k, v)| array &lt;&lt; MyObject.new(k, v) }` 可以吗?考虑到 `array.&lt;&lt;` 返回数组。 (2认同)

tok*_*and 47

正如@Rob所说,该块必须返回累加器(哈希).一些替代品:

Hash#update:

hash = ['a', 'b'].inject({}) { |m, e| m.update(e => e) }
Run Code Online (Sandbox Code Playgroud)

Enumerable#each_with_object:

hash = ['a', 'b'].each_with_object({}) { |e, m| m[e] = e }
Run Code Online (Sandbox Code Playgroud)

Hash#[]:

hash = Hash[['a', 'b'].map { |e| [e, e] }]
Run Code Online (Sandbox Code Playgroud)

使用Array#to_h(Ruby> = 2.1):

hash = ['a', 'b'].map { |e| [e, e] }.to_h
Run Code Online (Sandbox Code Playgroud)

使用Facets的Enumerable #mash:

require 'facets'
hash = ['a', 'b'].mash { |e| [e, e] }
Run Code Online (Sandbox Code Playgroud)

  • 不错的选择.我特别喜欢原始海报的技术和你的map-to-pairs-then-create-new-hash方法之间的区别:原始问题基本上是迭代 - 对于每个项目,在Hash上执行此操作 - 所以注入似乎过于复杂(因此错误).但是映射方法更多的是关于整体:将这个单元数组变成一对数组,然后将该对数组变成一个散列. (4认同)

the*_*Man 21

你应该研究一下,而不是使用注入Enumerable#each_with_object.

在哪里inject要求您返回累积的对象,each_with_object自动执行.

来自文档:

使用给定的任意对象迭代每个元素的给定块,并返回最初给定的对象.

如果没有给出块,则返回枚举器.

例如:

evens = (1..10).each_with_object([]) {|i, a| a << i*2 }
#=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
Run Code Online (Sandbox Code Playgroud)

所以,更接近你的问题:

[1] pry(main)> %w[a b].each_with_object({}) { |e,m| m[e] = e }
=> {"a"=>"a", "b"=>"b"}
Run Code Online (Sandbox Code Playgroud)

请注意injecteach_with_object反转生成的参数的顺序.