Ruby range.reduce与哈希累加器

问题描述 投票:4回答:2

我有这个方法

def heights
  (60..68).reduce({}) { |h, i| h.merge!( { %(#{i/12}'#{i%12}") => i } ) }
end

它返回高度的哈希值

{
  "5'0\"" => 60, "5'1\"" => 61, "5'2\"" => 62,
  "5'3\"" => 63, "5'4\"" => 64, "5'5\"" => 65,
  "5'6\"" => 66, "5'7\"" => 67, "5'8\"" => 68
}

这就是我想要的。但是,我不喜欢使用merge!方法。我更倾向于使用hash[key] = value语法进行赋值:

def heights
  (60..68).reduce({}) { |h, i| h[%(#{i/12}'#{i%12}")] = i }
end

但是这段代码会引发错误。我知道使用reduce,在你的管道中你可以命名你的累加器和元素。

我也明白这一点

sum = 0
(1..5).each { |i| sum += i }

相当于

(1..5).reduce(0) { |sum, i| sum + i }

那么为什么不这样呢

hash = {}
(1..5).each { |i| hash[i.to_s] = i }

工作相同

(1..5).reduce({}) { |hash, i| hash["#{i}"] = i }
ruby hash range
2个回答
3
投票

reduce阻止应该返回新的累加器。在你的情况下

(1..5).reduce({}) { |hash, i| hash["#{i}"] = i }

block返回i,这是一个整数,因此在第二次迭代时,您将尝试在整数上调用[]。你需要它:

(1..5).reduce({}) { |hash, i| hash["#{i}"] = i; hash }

6
投票

您可以使用each_with_object而不是reduce

(60..68).each_with_object({}) { |i, h| h[%(#{i/12}'#{i%12}")] = i }

enumerable.each_with_object(obj) { ... }返回obj所以你不需要在; h所需的块中使用人工感觉的reduce

请注意,块的参数顺序与reduce不同。

© www.soinside.com 2019 - 2024. All rights reserved.