summing values in a hash?

Discussion in 'Ruby' started by Jen, Mar 22, 2011.

  1. Jen

    Jen Guest

    Hi,

    Is there an inbuilt method to sum all values in a hash and return the
    result?

    I.E something like puts hash[values].sum

    If so could someone please point me at the correct section of the ruby docs?

    thanks,
    Jen.
    Jen, Mar 22, 2011
    #1
    1. Advertising

  2. [Note: parts of this message were removed to make it a legal post.]

    On Tue, Mar 22, 2011 at 12:57 PM, Jen <> wrote:

    > Is there an inbuilt method to sum all values in a hash and return the
    > result?
    >
    > I.E something like puts hash[values].sum
    >


    You could try

    hash.values.inject { |a, b| a + b }

    Alternatively, you have the shorter form, inject(&:+) or inject:)+)
    depending on your version of Ruby. 1.8.7 and higher should support all
    three.
    Adam Prescott, Mar 22, 2011
    #2
    1. Advertising

  3. There's no built in method to do that. You can do it with:

    hash = { :a => 1, :b => 6, :c => 20 }

    p hash.inject(0) { |sum, tuple| sum += tuple[1] } # => 27

    On Tuesday, March 22, 2011 01:57:27 pm Jen wrote:
    > Hi,
    >
    > Is there an inbuilt method to sum all values in a hash and return the
    > result?
    >
    > I.E something like puts hash[values].sum
    >
    > If so could someone please point me at the correct section of the ruby
    > docs?
    >
    > thanks,
    > Jen.
    Andrea Dallera, Mar 22, 2011
    #3
  4. On Tue, Mar 22, 2011 at 2:01 PM, Adam Prescott <> wrote:
    > On Tue, Mar 22, 2011 at 12:57 PM, Jen <> wrote:
    >
    >> Is there an inbuilt method to sum all values in a hash and return the
    >> result?
    >>
    >> I.E something like puts hash[values].sum
    >>

    >
    > You could try
    >
    > hash.values.inject { |a, b| a + b }
    >
    > Alternatively, you have the shorter form, inject(&:+) or inject:)+)
    > depending on your version of Ruby. 1.8.7 and higher should support all
    > three.


    You should rather use a different idiom because your solution breaks
    for empty Hash:

    irb(main):001:0> {}.values.inject {|a,b|a+b}
    => nil
    irb(main):002:0> {}.values.inject(0) {|a,b|a+b}
    => 0

    Kind regards

    robert


    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Mar 22, 2011
    #4
  5. Jen

    Robert Dober Guest

    On Tue, Mar 22, 2011 at 2:05 PM, Robert Klemme
    <> wrote:
    > On Tue, Mar 22, 2011 at 2:01 PM, Adam Prescott <> wrote:
    >> On Tue, Mar 22, 2011 at 12:57 PM, Jen <> wrote:
    >>
    >>> Is there an inbuilt method to sum all values in a hash and return the
    >>> result?
    >>>
    >>> I.E something like puts hash[values].sum
    >>>

    >>
    >> You could try
    >>
    >> hash.values.inject { |a, b| a + b }
    >>
    >> Alternatively, you have the shorter form, inject(&:+) or inject:)+)
    >> depending on your version of Ruby. 1.8.7 and higher should support all
    >> three.

    >
    > You should rather use a different idiom because your solution breaks
    > for empty Hash:
    >
    > irb(main):001:0> {}.values.inject {|a,b|a+b}
    > => nil
    > irb(main):002:0> {}.values.inject(0) {|a,b|a+b}
    > => 0

    slightly better, because working ;)
    .inject(0){|a,(_,b)|a+b}
    Cheers
    R.
    Robert Dober, Mar 22, 2011
    #5
  6. On Tue, Mar 22, 2011 at 3:13 PM, Robert Dober <> wrot=
    e:
    > On Tue, Mar 22, 2011 at 2:05 PM, Robert Klemme
    > <> wrote:
    >> On Tue, Mar 22, 2011 at 2:01 PM, Adam Prescott <> wr=

    ote:
    >>> On Tue, Mar 22, 2011 at 12:57 PM, Jen <> wrote:
    >>>
    >>>> Is there an inbuilt method to sum all values in a hash and return the
    >>>> result?
    >>>>
    >>>> I.E something like puts hash[values].sum
    >>>>
    >>>
    >>> You could try
    >>>
    >>> hash.values.inject { |a, b| a + b }
    >>>
    >>> Alternatively, you have the shorter form, inject(&:+) or inject:)+)
    >>> depending on your version of Ruby. 1.8.7 and higher should support all
    >>> three.

    >>
    >> You should rather use a different idiom because your solution breaks
    >> for empty Hash:
    >>
    >> irb(main):001:0> {}.values.inject {|a,b|a+b}
    >> =3D> nil
    >> irb(main):002:0> {}.values.inject(0) {|a,b|a+b}
    >> =3D> 0

    > slightly better, because working ;)
    > =A0 =A0.inject(0){|a,(_,b)|a+b}


    What do you mean by that? Where was my solution not working?

    robert


    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Mar 22, 2011
    #6
  7. Jen

    Robert Dober Guest

    On Tue, Mar 22, 2011 at 4:08 PM, Robert Klemme
    <> wrote:
    jruby -e 'p( {:a=>42}.inject(0){|a,b|a+b})'
    TypeError: Array can't be coerced into Fixnum
    + at org/jruby/RubyFixnum.java:333
    __file__ at -e:1
    each at org/jruby/RubyHash.java:1167
    inject at org/jruby/RubyEnumerable.java:816
    (root) at -e:1

    I recon you where coming from Hash#values, however on applying the
    code to an empy hash, where it works of course the reader could be
    missled

    Cheers
    Robert


    --
    The 1,000,000th fibonacci number contains '42' 2039 times; that is
    almost 30 occurrences more than expected (208988 digits).
    N.B. The 42nd fibonacci number does not contain '1000000' that is
    almost the expected 3.0e-06 times.
    Robert Dober, Mar 22, 2011
    #7
  8. On Tue, Mar 22, 2011 at 12:57 PM, Jen <> wrote:
    > Is there an inbuilt method to sum all values in a hash and return the
    > result?
    > I.E something like puts hash[values].sum
    > If so could someone please point me at the correct section of the ruby docs?


    Maybe write your own method because:
    1. it may be quicker than searching for an "inbuilt" method;
    2. it may run faster than using inject.

    require "benchmark"
    kt = 100_000
    nn = 20

    hash = Hash.new
    (1 .. nn).each { |nv| hash[ nv.to_s ] = nv }
    s1 = s2 = s3 = s4 = nil

    class Hash
    def mysum()
    s = 0
    each_value { |v| s += v }
    s
    end
    end

    sv = (nn * (nn + 1)) / 2
    puts; puts "summing 1..#{nn} #=> #{sv}; kt=#{kt};"

    Benchmark.bmbm do |bm|
    bm.report("1"){kt.times{s1=hash.values.inject{ |a, b| a + b } }}
    bm.report("2"){kt.times{s2=hash.inject(0){ |sum, tuple| sum += tuple[1] } }}
    bm.report("3"){kt.times{s3=hash.inject(0){|a,(_,b)|a+b} }}
    bm.report("4"){kt.times{s4=hash.mysum }}
    end
    puts "#{s1.inspect} #{s2.inspect} #{s3.inspect} #{s4.inspect}"


    ruby 1.9.1p430 (2010-08-16 revision 28998) [i386-mingw32]

    summing 1..20 #=> 210; kt=100000;
    user system total real
    1 3.057000 0.000000 3.057000 ( 3.057547)
    2 4.587000 0.000000 4.587000 ( 4.630071)
    3 4.524000 0.000000 4.524000 ( 4.525069)
    4 1.653000 0.000000 1.653000 ( 1.650026)
    210 210 210 210

    summing 1..2000 #=> 2001000; kt=1000;
    user system total real
    1 2.340000 0.000000 2.340000 ( 2.335036)
    2 4.711000 0.000000 4.711000 ( 4.705072)
    3 4.617000 0.000000 4.617000 ( 4.635071)
    4 1.529000 0.000000 1.529000 ( 1.530024)
    2001000 2001000 2001000 2001000
    Colin Bartlett, Mar 22, 2011
    #8
  9. On Tue, Mar 22, 2011 at 4:31 PM, Robert Dober <> wrot=
    e:
    > On Tue, Mar 22, 2011 at 4:08 PM, Robert Klemme
    > <> wrote:
    > =A0jruby -e 'p( {:a=3D>42}.inject(0){|a,b|a+b})'
    > TypeError: Array can't be coerced into Fixnum
    > =A0 =A0 =A0 =A0 + at org/jruby/RubyFixnum.java:333
    > =A0__file__ at -e:1
    > =A0 =A0 =A0each at org/jruby/RubyHash.java:1167
    > =A0 =A0inject at org/jruby/RubyEnumerable.java:816
    > =A0 =A0(root) at -e:1
    >
    > I recon you where coming from Hash#values, however on applying the
    > code to an empy hash, where it works of course the reader could be
    > missled


    My code explicitly included #values so it would not be affected by the
    error you posted - even for non empty Hash. Please read what I wrote.

    Cheers

    robert

    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Mar 22, 2011
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Summing a list

    , Sep 22, 2005, in forum: XML
    Replies:
    2
    Views:
    502
  2. Alf P. Steinbach
    Replies:
    2
    Views:
    521
    Chris Theis
    Feb 5, 2004
  3. Yaroslav Bulatov

    Microbenchmark: Summing over array of doubles

    Yaroslav Bulatov, Aug 1, 2004, in forum: Python
    Replies:
    9
    Views:
    384
    Christopher T King
    Aug 3, 2004
  4. Replies:
    0
    Views:
    502
  5. rp
    Replies:
    1
    Views:
    491
    red floyd
    Nov 10, 2011
Loading...

Share This Page