From: Tamara Temple Date: 2013-06-25T17:32:53+09:00 Subject: Re: Sum method through while loops or iteration Eric D. wrote: > I am trying to create a sum method for an empty array, that will return > "0" if there is nothing in it and the sum of the values if there are > values called through it. I have seen other ways on the internet, but I > am relatively new to this, and am under the impression that this can be > done with while loops or .each iteration. Below are various things I > tried, some were actual thoughts some were out of sheer frustration. I applaud all efforts to learn how things work. That said, there is a method which does this already: inject/reduce (they are synonyms). But let's look at what you're doing. > Thanks for your help! > 1. > def sum (array) The method accepts an array passed in local variable `array`. > > array = [] You destroy any information you've passed in `array` by resetting it here. > while array >0 This construction makes little sense, as an Array (`array` is an instance of the Array class) cannot be compared to a Fixnum (which is what 0 is.) But then: > array.each { |a| sum+=a } You use another loop to run through `array`. This is probably what you mean entirely and there is no need for an outer while loop. However, the local variable `sum` is declared implicitly inside the block {|a| sum+=a}. There are two problems here: 1. `sum` is initially nil, and nil does not accept += (or +) 2. `sum` will not be available outside the block > end > > 2. > > def sum > x= [] This time, you aren't overwriting any method input, but you also hardwire the `x` array to an empty array. Not a very useful method. > x.each{|element| element +element } More problems here. You've omitted the egregious while loop, which is good. But your block is not doing anything in particular. The current element in `x` is added to itself, but isn't stored anywhere. Trying this out in irb: 2.0.0p195 :001 > x = (1..10).to_a => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 2.0.0p195 :002 > x.each{|e| e+e} => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 2.0.0p195 :003 > To see what's happening inside the block, let's add `tap`: 2.0.0p195 :003 > x.each{|e| (e+e).tap{|t| puts "tapped e+e: #{t}"} } tapped e+e: 2 tapped e+e: 4 tapped e+e: 6 tapped e+e: 8 tapped e+e: 10 tapped e+e: 12 tapped e+e: 14 tapped e+e: 16 tapped e+e: 18 tapped e+e: 20 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Probably not what you wanted. > end > > 3. > def sum(array) > > while array.length > 0 This may seem like it should work, but you are not actually changing the length of `array` so it should go on forever. > puts "#{array[x+y+z]}" This is insteresting, but where do you define the variables `x`, `y`, and `z`? This should have elicited an error message straight away. > else > puts "0" There was no `end` in this block. Let's drop back a second and just look at the algorithm one can use to find the sum of number in an array. No ruby, just pseudo-code. Given an array of numeric elements, When I initialize a sum variable to zero, And I loop through the array with an index, And I add the value of the array element at the current index to the sum variable, Then I will have the sum of the elements in the array. Someone's already given the inject/reduce version: (using x from before) 2.0.0p195 :007 > x.inject(:+) => 55 But let's look at this in a method: === sum.rb def sum(a) # Given an array of numeric elements, sum = 0 # When I initialize a sum variable to zero, a.each_index do |i| # And I loop through array with an index, sum += a[i] # And I add the value of the array element # at the current index to the sum # variable, end sum # Then I will have the sum of the elements in the array. end === 2.0.0p195 :010 > def sum(a) ; sum=0;a.each_index{|i| sum+=a[i]}; sum; end => nil 2.0.0p195 :011 > sum x => 55 There's at least a dozen ways to write this; this is but one. Comparing the method sum to inject, I much prefer inject.