2011-12-24 14 views
7

मैं जैसे इनपुट लेने के लिए करना चाहते हैं:मैं श्रेणियों की सरणी के रूप में पूर्णांक की सरणी को सारांशित कैसे करूं?

[1,2,4,5,6,7,9,13] 

और निम्नलिखित की तरह कुछ में बदल:

[[1,2],[4,7],[9,9],[13,13]] 

प्रत्येक उप-सरणी पूर्णांकों की एक श्रृंखला का प्रतिनिधित्व करता है।

+2

में पेश किया गया था अगर वहाँ यह पहले से ही करने के लिए कोड है आप पूछ रहे हैं? क्या आप पूछ रहे हैं क्योंकि आप अपना खुद का रोल करने और इसे लागू करने में परेशानी का प्रयास कर रहे हैं? – bobbymcr

+0

मैं अपना खुद का रोलिंग कर रहा हूं। ऐसा लगता है कि रुबी में इस तरह की चीज को लागू करने के लिए हमेशा दिलचस्प तरीके हैं। – Larsenal

+0

किन स्थितियों को निर्मित किया जाना चाहिए? – cvshepherd

उत्तर

19

कार्यात्मक दृष्टिकोण Enumerable#chunk का उपयोग कर:

xs.enum_for(:chunk).with_index { |x, idx| x - idx }.map do |diff, group| 
    [group.first, group.last] 
end 
# => [[1, 2], [4, 7], [9, 9], [13, 13]] 

यह कैसे काम करता है: एक बार अनुक्रमित, सरणी में लगातार तत्व एक ही x - idx है, इसलिए हम हिस्सा करने के लिए है कि मूल्य का उपयोग करें (लगातार आइटम का समूह) इनपुट सरणी। अंत में हमें जोड़े बनाने के लिए प्रत्येक समूह के पहले और अंतिम तत्वों को लेने की आवश्यकता है।

+0

यह वास्तव में अच्छा लगता है। पूरी तरह से नई खंड विधि के बारे में भूल गए। – cvshepherd

+2

और इसे एक और कदम उठाने के लिए, '.map {| min, max | न्यूनतम == अधिकतम? न्यूनतम: न्यूनतम .. अधिकतम} 'का परिणाम होगा: '[1..2, 4..7, 9, 13]'। –

+0

या, '[जोड़े.first [0], pair.last [0]] ' ' जोड़े.first [0] .. pair.last [0] 'सभी पदों में श्रेणियां प्राप्त करने के लिए बदलें:' [1। .2, 4..7, 9.9, 13..13] '। –

0

एक और दृष्टिकोण

def summarize(x) 
    x.inject([]) do |acc, value| 
    if acc.last && acc.last[1] + 1 == value 
     acc.last[1] = value 
     acc 
    else 
     acc << [value,value] 
    end 
    end 
end 

Larsenal की विधि के समान है, लेकिन बोरिंग सामान का प्रबंधन करने के इंजेक्षन का उपयोग कर।

3

हम्म, ठीक है, यह नहीं tokland's कृति है, लेकिन मैं यह एक अच्छा सरल समाधान हो सकता है लगता है ...

[1,2,4,5,6,7,9,13].inject([]) do |m, v| 
    if m.last.to_a.last == v.pred 
    m[-1][-1] = v 
    else 
    m << [v, v] 
    end 
    m 
end 
4

यह enumerable#slice_before विधि दस्तावेज़ से लगभग सीधे है:

ar = [1,2,4,5,6,7,9,13] 
prev = ar[0] 
ar.slice_before{|e|prev,prev2 = e,prev; prev2.succ != e}.map{|a|a.first..a.last} 
#=> [1..2, 4..7, 9..9, 13..13] 

यह अक्षर, तिथियों, .succ विधि के साथ कुछ भी काम करना चाहिए।

2

@tokland's very nice one से एक और भी आसान समाधान chunk_while उपयोग कर रहा है:

xs.chunk_while { |a, b| a + 1 == b }.map do |seq| 
    [seq.first, seq.last] 
end 

नोट: chunk_while रूबी 2.3

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