Reduce Hash Values

前端 未结 6 1478
南旧
南旧 2021-02-03 20:30

I am having trouble with the syntax for reduce. I have a hash of the following format:

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

I would like t

相关标签:
6条回答
  • 2021-02-03 20:50

    I know I'm excavating this one, but if you happen to use Rails, the .sum method can help:

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

    Advantage is that it returns 0 on empty hashes:

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

    I noticed it was Rails-specific only after typing this answer. I know the OP didn't add the Rails tag, but I figured it might be useful for people stopping by.

    Note that as of Ruby 2.4.0, .sum is now available.

    0 讨论(0)
  • 2021-02-03 20:51

    In case of a complex hash it might be easier to map it first to an array of values, then reduce:

    values = H.map do |k, v|
        # some complex logic here
    end
    values.reduce(:+)
    

    Or values.reduce(0, :+) if the array might be empty.

    0 讨论(0)
  • 2021-02-03 20:57

    You can make elem contain the value by splitting it up in 2 variables:

    H.reduce(0) {|memo, (key, val)| memo += val}
    
    0 讨论(0)
  • 2021-02-03 21:02

    Try this:

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

    or

    H.reduce(0) { |memo, (key, value)| memo += value }
    
    0 讨论(0)
  • 2021-02-03 21:03

    Use Enumerable#reduce, if you're ok with getting nil if the hash happens to be empty:

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

    To safely get 0 when the hash is empty, use:

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

    Here's a quick benchmark, for kicks. Note that it appears to be slightly faster to reduce just the values rather than values from the key/value pairs:

                                   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 讨论(0)
  • 2021-02-03 21:15
    h = {"Key1" => 1, "Key2" => 2}
    
    h.values.inject(0){|f,v| f += v.to_i }
    # => 3
    

    or

    h.values.inject(:+)
    # => 3
    
    0 讨论(0)
提交回复
热议问题