2015-09-30 14 views
5

मिलान के एन घटनाओं अप करने के लिए लगता है मैं निम्नलिखित सरणी है:रूबी गणनीय - तत्व

arr = [1, 3, 2, 5, 2, 4, 2, 2, 4, 4, 2, 2, 4, 2, 1, 5] 

मैं पहले तीन अजीब तत्वों से युक्त एक सरणी चाहते हैं।

मैं जानता हूँ कि मैं यह कर सकता है:

arr.select(&:odd?).take(3) 

लेकिन मैं पूरी सरणी के माध्यम से पुनरावृत्ति से बचने, और बदले में एक बार मैं तीसरे मैच मिल गया है वापस जाने के लिए चाहते हैं।

मैं निम्नलिखित समाधान के साथ आया था, जो मुझे लगता है कि मैं क्या चाहते है:

my_arr.each_with_object([]) do |el, memo| 
    memo << el if el.odd?; break memo if memo.size == 3 
end 

लेकिन वहाँ एक और अधिक सरल/ऐसा करने का मुहावरेदार तरीका है?

उत्तर

9

का प्रयोग करें एक lazy enumeratorEnumerable#lazy साथ:

arr.lazy.select(&:odd?).take(3).force 
# => [1, 3, 5] 

force मूल्यांकन करने के लिए आलसी प्रगणक मजबूर करने के लिए प्रयोग किया जाता है। या, आप first इस्तेमाल कर सकते हैं के रूप में यह उत्सुक है:

arr.lazy.select(&:odd?).first(3) 
# => [1, 3, 5] 
+0

मैंने पुष्टि की कि 'बल' काम करता है, लेकिन मुझे [रूबी लैंग] में एक को छोड़कर दस्तावेज नहीं मिल रहा है (http://docs.ruby-lang.org/ja/2.1.0/method/Enumerator=3a= 3aLazy/i/force.html)। क्या आप जानते हैं कि यह आरडीओसी में प्रलेखन में क्यों नहीं है? क्या ऐसा इसलिए है क्योंकि यह केवल 'to_a' का उपनाम है? – sawa

+3

एफवाईआई - आप 'arr.lazy.select (&: odd?) का उपयोग कर सकते हैं। पहले (3)' और 'बल' से बचें - 'टेक' आलसी है जबकि' पहला 'नहीं है। – Myst

+0

@sawa मैं इसे भी नहीं ढूंढ सकता। यदि आपको लगता है, तो मेरा जवाब संपादित करने के लिए स्वतंत्र महसूस करें। –

5

कोड और उदाहरण

arr.take_while.with_object([]) do |e,a| 
    a << e if e.odd? 
    a.size < 3 
end 
    #=> [1, 3, 5] 

बेंचमार्क

require 'fruity' 

def compare_em(arr, m) 
    compare(
    lazy:  -> { arr.lazy.select(&:odd?).take(m).force }, 
    take_while: -> { arr.take_while.with_object([]) { |e,a| 
         a << e if e.odd?; a.size < m } } 
) 
end 

n = 1e6 
arr = (1..n).to_a.shuffle 

प्राप्त पहले 1,000 अजीब तत्वों:

compare_em(arr, 1e3) 
    # Running each test 8 times. Test will take about 1 second. 
    # take_while is faster than lazy by 2x ± 1.0 

प्राप्त पहले 10,000 अजीब तत्वों:

compare_em(arr, 1e4) 
    # Running each test once. Test will take about 1 second. 
    # take_while is faster than lazy by 2x ± 1.0 

पहले 100,000 अजीब तत्व प्राप्त करें:

compare_em(arr, 1e5) 
    # Running each test once. Test will take about 3 seconds. 
    # take_while is faster than lazy by 2x ± 0.1 

मैं, lazy काफी अच्छा प्रदर्शन किया हैरान हूँ क्योंकि यह अक्सर बहुत धीमी है, अपेक्षाकृत, बेंचमार्क में

संबंधित मुद्दे