Reputation: 114
Is there a way to refactor this method using map? (this intention of this method is to return an array of prime numbers between 1 and the max parameter)
def primes(max)
prime_arr = []
(1..max).each {|i| prime_arr << i if is_prime?(i)}
prime_arr
end
is_prime?(val) returns true or false.
if i change my method to:
def primes(max)
(1..max).map {|i| i if is_prime?(i)}
end
The returned array has a nil value when the code blocks fails.
p primes(5)
#=> [1, 2, 3, nil, 5]
I know what I have works, but i'd rather not declare the array and return the array specifically if there's a better way to do it
Upvotes: 1
Views: 109
Reputation: 13921
require 'Prime'
MAX = 100
p Prime.each(MAX).to_a #=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31...
p (1..MAX).select(&:prime?) #=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31...
An alternative is to use grep if you want to select and transform:
primes = ->x{x.prime?} # (new lambda syntax)
p (1..100).grep(primes){|x| x.to_s} #=> ["2", "3", "5", "7", "11", "13", "17",...
Upvotes: 1
Reputation: 62003
Enumerable.reject
(or Enumerable.select
) are the correct methods to filter the sequence.
These filter methods only looks at the truthy-ness of the returned value and thus while returning i
in this case "works" (as i
is always a truthy value), the returned value is actually discarded (unlike map
) so the predicate should look more like:
c.reject {|i| !is_prime?(i)}
# or (inverting the double negative)
c.select {|i| is_prime?(i)}
# or (with &:)
c.select(&:is_prime?)
(See &:
for the magic behind the latter case.)
Also, since this is dealing with finding prime numbers, the Sieve of Eratosthenes might be a good read.
Upvotes: 2
Reputation: 114
Yeah... i just figured out A way while trying to explain it, but please feel free to show me a better way!
def primes(max)
(1..max).reject {|i| i if ! is_prime?(i)}
end
Upvotes: 0