Reputation: 1
I tried something like this:
def average_array_float(&array)
array.inject{ |sum, el| sum + el }.to_f / array.size
end
no success
array = [1, 2, 3]
def even_numbers(array)
array.select { |num| num.even? }
end
p array.even_numbers
reply:
$ bundle exec ruby main.rb
Traceback (most recent call last):
main.rb:7:in `<main>': private method `even_numbers' called for [1, 2, 3]:Array (NoMethodError)
exit status 1
what i am doing wrong?
Upvotes: 0
Views: 52
Reputation: 114128
You have to pass the array to the method:
def even_numbers(array)
array.select { |num| num.even? }
end
array = [1, 2, 3, 4, 5, 6]
even_numbers(array)
#=> [2, 4, 6]
The NoMethodError
in your example happens because if you define a method on the top-level, it becomes a private method of Object
:
Object.private_methods
#=> [:initialize, :inherited, :method_added, :method_removed, :method_undefined,
# :remove_const, :initialize_copy, :initialize_clone, :using, :public,
# :ruby2_keywords, :protected, :private, :included, :extended, :prepended,
# :even_numbers, :sprintf, :format, ...]
# ^^^^^^^^^^^^^
And since array
is an Object
, it can access that method (privately).
If you really wanted to add the method to Array
, you could open the corresponding class:
class Array
def even_numbers
select { |num| num.even? }
end
end
Which gives you:
[1, 2, 3, 4, 5, 6].even_numbers
#=> [2, 4, 6]
However, although this works, it's not advised to alter objects that are not your own, let alone Ruby's core classes.
Regarding your other method, you could use sum
and fdiv
:
def average(array)
array.sum.fdiv(array.size)
end
average([1, 2, 4])
#=> 2.3333333333333335
Or quo
if you prefer a precise result:
def average(array)
array.sum.quo(array.size)
end
average([1, 2, 4])
#=> (7/3)
Upvotes: 1