2013-10-31 60 views
1

有沒有一種方法可以使用map來重構此方法? (此意圖這種方法的是返回1和最大參數之間的素數的陣列)如果代碼塊的計算結果爲false,則跳過可枚舉#map上的值

def primes(max) 
    prime_arr = [] 
    (1..max).each {|i| prime_arr << i if is_prime?(i)} 
    prime_arr 
end 

is_prime?(val)返回真或假。

如果我改變方法:

def primes(max) 
(1..max).map {|i| i if is_prime?(i)} 
end 

返回的數組具有零值時,碼塊失敗。

p primes(5) 
#=> [1, 2, 3, nil, 5] 

我知道我必須工作,但我寧願不聲明數組,具體返回數組,如果有更好的方法來做到這一點

回答

2

Enumerable.reject(或Enumerable.select)是正確的方法來濾波器序列。

這些過濾方法只着眼於返回值的truthy岬,因此而在這種情況下返回i「作品」(如i始終是一個truthy值),返回的值實際上是丟棄的(不像map),所以謂語應該看起來更像:(後者落後的情況下神奇見&:

c.reject {|i| !is_prime?(i)} 

# or (inverting the double negative) 
c.select {|i| is_prime?(i)} 

# or (with &:) 
c.select(&:is_prime?) 

此外,由於這是處理尋找素數,Sieve of Eratosthenes可能是一個很好的閱讀。

+0

是啊,我意識到,張貼:)拒絕和選擇的問題秒後就是我一直在尋找。 – Brent

+0

這是一個關於如何避免地圖上的nils,注入等的問題(我是ruby的新手),我想最正確的方法是在最大值中包含Primes和Primes.each。 – Brent

0

啊...我只是想出一個辦法同時試圖解釋它,但請隨時給我一個更好的方法!

def primes(max) 
    (1..max).reject {|i| i if ! is_prime?(i)} 
end 
1
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... 

另一種方法是使用grep如果要選擇和改造:

primes = ->x{x.prime?} # (new lambda syntax) 
p (1..100).grep(primes){|x| x.to_s} #=> ["2", "3", "5", "7", "11", "13", "17",... 
+0

grep的例子很有趣,但真的需要探索更多([Proc#===](http://ruby-doc.org/core-2.0.0/Proc.html#method-i-3D-3D -3D)應該被提及,因爲它是它工作的全部原因;而lambda可以用'&:'to-proc方法替代)。我通常只是在鏈中使用'select..map..'。 – user2864740

+0

Grep使用案例相等運算符來選擇項目。您可以使用正則表達式或類名稱。正如你所提到的lambda(或Proc)與===相比時被調用。這在創建case語句或想要從複雜鏈函數重構邏輯時非常方便。 – hirolau

+0

最好,在好信息應該去的答案! – user2864740