Reputation: 9765
I spent some time trying to find a way to do basic operations on each element in an array such as sum, round, etc.
I didn't see a built-in way to do this, so I tried to create my own after finding "Generic 'sum' And 'mean' Methods For Ruby Arrays".
Can someone explain why my round
method doesn't work?
class Array
def sum
inject(nil) { |sum, x| sum ? sum + x : x }
end
def mean
sum / size
end
def round(p)
inject(nil) { |x| (x * 10 ^ (p-1)).floor / 10 ^ (p - 1) }
end
end
puts [1.1234, 1.45656, 1.546567, 1.4577887].mean
puts [1.1234, 1.45656, 1.546567, 1.4577887].round(6)
Upvotes: 0
Views: 571
Reputation: 110675
You want the following.
class Array
def sum
inject(:+)
end
def mean
sum / size.to_f
end
def round(p)
map { |n| n.round(p) }
end
end
puts [1.1234, 1.45656, 1.546567, 1.4577887].mean
1.3960789249999999
puts [1.1234, 1.45656, 1.546567, 1.4577887].round(6)
1.1234
1.45656
1.546567
1.457789
Note that sum.to_f
(or size.to_f
) is needed when the array contains only integers. If arr.sum = 3
and arr.size = 2
, sum / size #=> 1
whereas sum / size.to_f #=> 1.5
.
Upvotes: 2
Reputation: 36101
To answer the why part of your question, there are three issues with your implementation:
Conceptual: inject
is used to get a bunch of things and combine them into one thing. Here you have things and want to juxtapose the same number of other things. The method to do that is map
:
[1, 2, 3].inject(:+) # => 6
[-1, 2, -3].map(&:abs) # => [1, 2, 3]
Syntactical: ^
is a bitwise XOR, not power to. To do that, the operator is **
.
1.77
one decimal point:
(17.7).floor / 10 = 1.7
Upvotes: 1