0

I am trying to write a small function with ruby that gets fed a array from the user and then sums up the data in the array. I have written it as

    def sum(a)
      total = 0
      a.collect { |a| a.to_i + total }
    end

The function then runs through a rspec, which tests it by initially feeding into it a blank array. This this causes the following error

    sum computes the sum of an empty array
    Failure/Error: sum([]).should == 0
    expected: 0
        got: [] (using ==)

So its telling me that when it feeds the blank array in, its supposed to get 0 but instead its getting the array. I tried putting in a if statement written as

    def sum(a)
      total = 0
      a.collect { |a| a.to_i + total }
      if total = [] then { total = 0 end }
    end

but it gives me an error saying

    syntax error, unexpected '}', expecting => (SyntaxError)

what am I doing wrong?

Mike F
  • 309
  • 1
  • 8
  • 18

3 Answers3

2

You shouldn't use map/collect for this. reduce/inject is the appropriate method

def sum(a)
  a.reduce(:+)
  # or full form
  # a.reduce {|memo, el| memo + el }

  # or, if your elements can be strings
  # a.map(&:to_i).reduce(:+)
end
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
  • This fails for arrays like `a = ["123","23","345","678"]`. I think Mike F is using `.to_i` specifically. – 000 Apr 04 '13 at 17:34
  • How does `a.map(&:to_i).reduce(:+)` perform with memory usage on large arrays? Would it double the memory usage, or is Ruby smart enough to do this smarter? – 000 Apr 04 '13 at 17:37
  • In ruby 2.0 this could be made lazy. In previous versions, yes, it will create a temp array. Your version is more efficient in that sense. But mine is prettier :) – Sergio Tulentsev Apr 04 '13 at 17:41
0

See here: How to sum array of numbers in Ruby?

and here: http://www.ruby-doc.org/core-1.9.3/Enumerable.html#method-i-inject

def sum(a)
    array.inject(0) {|sum,x| sum + x.to_i }
end
Community
  • 1
  • 1
000
  • 26,951
  • 10
  • 71
  • 101
  • this worked, thank you. Does it work because it is telling the program to add a zero to each location if that location is blank? – Mike F Apr 05 '13 at 01:28
  • It converts every location to an integer. If it's blank, then it converts to zero. – 000 Apr 05 '13 at 01:52
0
gets.split.map(&:to_i).inject(:+)
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329