Вопрос

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

Это было полезно?

Решение

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.

Другие советы

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",...

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top