Älphä Blüë said:
Are you posting here because you want comments/suggestions? If so,
here's my 2c.
(1) Passing enumerated values 1,2,3 is not very Ruby-like. If you want
to go this way, then I'd suggest symbols: :arithmetic, :geometric,
:harmonic
(2) However, IMO it's also code smell if you write something like
case A
when X
.. do one thing
when Y
.. do another thing
... etc
end
There's usually a better way to ask directly for what you want.
Suggestions:
(a) add some methods directly to class Array, in the same way as 'sum'
class Array
def arithmetic_mean
self.sum / self.size
end
def geometric_mean
... etc
end
end
puts [1,2,3,4,5].arithmetic_mean
This is perfectly fine within your own apps, but modifying core classes
may not be acceptable in a shared library (depending on who your target
audience is)
(b) wrap an array with an object which does the calculation
class Mean
def initialize(arr)
@arr = arr
end
def arithmetic
@arr.sum / @arr.size
end
... etc
end
puts Mean([1,2,3,4,5]).arithmetic
Note that creating an object like this is a cheap operation in Ruby.
You're not copying the array elements, just a reference to the array
itself.
(3) It is considered extremely bad form to write
if !an_array.is_a? Array: raise "mean(#{an_array}) error: #{an_array}
is not an array." end
You should simply leave this out. This lets the user pass in any object
which responds to the particular methods you call on it (each, sum,
size). This is the "duck typing" principle - if someone wants to create
an object which behaves like an Array, even though it is not actually an
Array, why should you forbid them from using it?
If they pass in an incompatible object, Ruby will generate an exception
for you anyway. Admittedly it might not be quite as obvious what's
happening, but it will typically be something along the lines of
NoMethodError: object does not respond to 'sum'
which tells you exactly what the problem is.
(4) You can rewrite the following using inject:
an_array.each do |a|
n_sum += (1.0 / a)
end
(5) If I were you, I would rewrite this not to use sum and size, but
just to iterate over the collection using 'each' (or something which in
turn calls 'each', like 'inject'), calculating the total and count as
you go. This would allow your code to work on any object which is
Enumerable, such as
(1..5).arithmetic_mean
Regards,
Brian.