Ruby Array.inject问题 - 看不到它

时间:2009-09-04 19:37:16

标签: ruby

我试图将数组中的值存储到散列(数组值是键,值只是0)。这是我的代码。有什么想法吗?

[1, 2, 3, 4].inject({}) {|result, e| result[e] = 0} 

这是我得到的错误。

oMethodError: undefined method `[]=' for 0:Fixnum
    from (irb):1
    from (irb):1:in `inject'
    from (irb):1:in `each'
    from (irb):1:in `inject'
    from (irb):1
    from :0

6 个答案:

答案 0 :(得分:8)

问题是result[e] = 0返回操作的结果,即0,并且会在您尝试在其上调用[]=的情况下进行下一次迭代。您可以通过执行以下操作来解决此问题:

[1, 2, 3, 4].inject({}) {|result, e| result[e] = 0; result }

答案 1 :(得分:8)

“结果”的事情很好,但作为一种品味,我更喜欢这种方式:

[1,2,3,4].inject({}) {|result,e| result.merge!(e=>0)}

如果这是性能关键代码,那么品味就是其代价。这是一个快速的基准测试,可以完成这项操作一百万次。

在Ruby 1.8.5中

merge: 22s
merge!: 14s
; result: 9s

在Ruby 1.9.1中

merge: 18s
merge!: 11s
; result: 5s

答案 2 :(得分:2)

result[e] = 0的返回值为0,而不是result。你必须这样做:

[1, 2, 3, 4].inject({}) {|result, e| result[e] = 0; result}

(或使用merge代替[]=或使用each代替inject

答案 3 :(得分:0)

你真的应该使用合并!而不是在这种情况下合并。没有理由在每次迭代时创建新的哈希值。

[1,2,3,4].inject({}) {|result,e| result.merge!(e=>0)}

答案 4 :(得分:0)

它需要两行,但你也可以这样做

hash = {}
[1,2,3,4].each{|key| hash[key] = 0}

答案 5 :(得分:0)

如果你的数组是一个没有嵌套其他数组的简单数组,那么我会使用array-dereferencing哈希构造方法:

Hash[*[1,2,3,4].zip(Array.new(4,0)).flatten]

或者可能更笼统:

如果有嵌套数组,则只需要压平一个级别,并且由于没有flatten_once的ruby命令,您只需通过连接手动完成。好处是你可以在连接期间交错零,这样你就不必再压缩了它:

Hash[*[1,2,3,4].inject([]){|s,x| s.concat([x,0])}]

在Ruby 1.8.6中,在我的机器上快速完成1000000次迭代,这给了我:

aforementioned merge! method:       34s
Hash[*...).concat([x,0])}] method:  25s
aforementioned result! method:      22s
Hash[*...).flatten] method:         15s