2010-03-25 13 views
10

रूबी 1.8.6रुबी ऐरे में आसन्न समान तत्वों को हटाएं?

मेरे पास संख्यात्मक मान युक्त एक सरणी है। मैं इसे कम करना चाहता हूं जैसे कि उसी मान के अनुक्रम उस मान के एक उदाहरण में कम हो जाते हैं।

तो मैं

a = [1, 1, 1, 2, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3] 

चाहते

[1, 2, 3, 2, 3] 

को कम करने के लिए आप देख सकते हैं, Array#uniq इस मामले में काम नहीं करेगा।

मैं निम्नलिखित है, जो काम करता है:

(a.size - 1).downto(1) { |i| a[i] = nil if a[i - 1] == a[i] } 

किसी को भी कुछ कम बदसूरत के साथ आ सकते हैं?

उत्तर

19

सरल, leanest समाधान के लिए, आप विधि Enumerable#chunk इस्तेमाल कर सकते हैं। यदि आप पुरानी रूबी का उपयोग करने के लिए पर्याप्त भाग्यशाली हैं, तो आप मेरे backports मणि और require 'backports/1.9.2/enumerable/chunk' का उपयोग कर सकते हैं।

+0

मैंने अभी यह कोशिश की - उत्कृष्ट। धन्यवाद! –

+1

आपको x.first की आवश्यकता नहीं है, आप बस कह सकते हैं।नक्शा (और: पहला) – Darkmouse

+0

@DarkMouse आप 1.8.6 :-) वास्तव में में किया था। यह 4 साल पहले प्रासंगिक था, लेकिन आज ज्यादा नहीं। मैंने अपना उत्तर –

0

मैं केवल इस

a.each_with_index{|item,i| a[i] = nil if a[i] == a[i+1] }.compact 

के बारे में सोच सकते हैं, लेकिन यह लगभग बराबर ही है।

1

जब तक आप कर रहे हैं बहुत गति कि ब्लॉक, पर गणना करेगा मैं तो आप बस इच्छित उत्पादन प्राप्त करने के लिए अपने ब्लॉक के अंत में यह पंक्ति जोड़ सुझाव के साथ संबंध:

a.compact! 

कि सिर्फ होगा (भावी डुप्लिकेट) सभी nil तत्वों आप सरणी पहले से परिचित कराया निकालने के लिए, अपने वांछित उत्पादन के गठन: [1, 2, 3, 2, 3]

आप एक और कलन विधि चाहते हैं, यहाँ से कुछ दूर भद्दा है आपका अपना। :-)

require "pp" 

a = [1, 1, 1, 2, 2, 3, 3, 3, 3, 2, 2, 2, 3, 3, 3] 

i = 0 

while i < a.size do 
    e = a[i] 
    j = i 

    begin 
    j += 1 
    end while e == a[j] 

    for k in i+1..j-1 do 
    a[k] = nil 
    end 

    i = j 
end 

pp a 
a.compact! 
pp a 

आप उत्पादन देता है:

[1, nil, nil, 2, nil, 3, nil, nil, nil, 2, nil, nil, 3, nil, nil] 
[1, 2, 3, 2, 3] 

मेरी राय में, अपने कोड ठीक है। बस a.compact! कॉल जोड़ें और आपको क्रमबद्ध किया गया है।

a.chunk{|n| n}.map(&:first) 

यह रूबी 1.9.2 में पेश किया गया:

5
a.inject([]){|acc,i| acc.last == i ? acc : acc << i } 
+0

अपडेट किया है, मुझे एक बार यह भी मिला, एक बार मुझे # इंजेक्ट 'याद आया। यह मेरे द्वारा पोस्ट किए गए प्रयास से निश्चित रूप से साफ है और यह बहुत अधिक "रूबीश" है। '# Chunk' बात को हरा करना मुश्किल है, हालांकि ... –

1

एक और समाधान:

acc = [a[0]] 
a.each_cons(2) {|x,y| acc << y if x != y} 

या

a.each_cons(2).inject([a[0]]) {|acc, (x,y)| x == y ? acc : acc << y} 
+0

मैं' की आवश्यकता होती है 'enumerator'' है, जो अक्सर एक गलती है के बारे में भूल करने लगते हैं। मुझे यकीन है कि मुझे अपने कोड में एक दर्जन स्थान मिल सकते हैं जहां मुझे '# प्रत्येक_cons' का उपयोग करना चाहिए था। धन्यवाद! –

1

संख्या सभी एकल 0-9 अंक हैं: a.join.squeeze('0-9').each_char.to_a काम करना चाहिए।

+0

मेरे मामले में वे नहीं हैं, लेकिन आप मुझे विधि के लिए नाम दिया है कि अगर मैं बंदर-पैच: 'सरणी # squeeze' –

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