减少哈希值。

42

我在使用reduce函数时遇到了语法问题。我有一个以下格式的哈希表:

H = {"Key1" => 1, "Key2" => 2}

我想使用reduce函数来计算这个函数中值的总和。

类似以下的内容:

H.reduce(0) {|memo, elem| memo+=elem}

我知道这是错的。我不明白如何将elem作为哈希表的值。


6
尝试:H.values.reduce(:+) - Diego Basch
6个回答

87
您可以通过将其拆分为两个变量来使elem包含该值:
H.reduce(0) {|memo, (key, val)| memo + val}

6
我会写成memo + val,避免让人们认为更新memo是有帮助的。 - Ludovic Kuty
完全同意@lkuty的观点,memo的+=变异是不必要和误导性的。 - Pierre

42

如果你可以接受哈希表为空时返回nil,那么请使用Enumerable#reduce

H.values.reduce(:+) # => 3
Hash.new.values.reduce(:+) # => nil

若要在哈希为空时安全地获得0,请使用:

H.values.reduce(0) { |sum,x| sum + x } # or...
H.reduce(0) { |sum,(key,val)| sum + val } # ...if you need to inspect the key

这里是一个快速的基准测试,只是为了好玩。请注意,仅缩减值似乎比从键/值对中缩减值要稍微快一些:

                               user     system      total        real
H.values.reduce(:+)        4.510000   0.080000   4.590000 (  4.595229)
H.values.reduce(0) {...}   4.660000   0.080000   4.740000 (  4.739708)
H.reduce(0) {...}          5.160000   0.070000   5.230000 (  5.241916)
require 'benchmark'

size = 1_000
hash = Hash[* Array.new(size*2) { rand } ]

N=10_000
Benchmark.bm(24) do |x|
  x.report('H.values.reduce(:+)')      { N.times { hash.dup.values.reduce(:+) } }
  x.report('H.values.reduce(0) {...}') { N.times { hash.dup.values.reduce(0) { |sum,x| sum + x } } }
  x.report('H.reduce(0) {...}')        { N.times { hash.dup.reduce(0) { |sum,(_,v)| sum + v } } }
end

请注意,如果哈希表为空,则此代码不会返回0。您需要使用下面的备忘录版本。 - Josh Bodah

6

试试这个:

H.reduce(0) { |memo, elem| memo += elem[1] }

或者

H.reduce(0) { |memo, (key, value)| memo += value }

4
我会将“memo + value”写成来避免让人们认为更新“memo”是有帮助的。 - Ludovic Kuty

2

虽然这个问题比较老,但如果你正在使用Rails,.sum方法可能会有所帮助:

H = {"Key1" => 1, "Key2" => 2}
=> {"Key1"=>1, "Key2"=>2}
> H.values.sum
=> 3

优点是当哈希表为空时,它会返回0

> {}.values.sum
=> 0
> {}.values.reduce(:+)
=> nil

在回答之前,我注意到这只适用于Rails。我知道OP没有添加Rails标签,但我认为这可能对其他人有用。

请注意,从Ruby 2.4.0开始,.sum现在可用


1
.sum现在已经在Ruby 2.4中实现Enumerable#sum - user3162553

1
h = {"Key1" => 1, "Key2" => 2}

h.values.inject(0){|f,v| f += v.to_i }
# => 3

或者

h.values.inject(:+)
# => 3

0
如果遇到一个复杂的哈希表,将其先映射到一个值数组,然后进行简化可能会更容易:
values = H.map do |k, v|
    # some complex logic here
end
values.reduce(:+)

如果数组可能为空,则使用values.reduce(0, :+)


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