Eric D. [email protected] 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:
-
sum is initially nil, and nil does not accept += (or +)
-
sum will not be available outside the block
end
-
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
-
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.