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.