2009-10-19 15 views
7

किसी विशिष्ट कुंजी के आधार पर ऑब्जेक्ट्स की सरणी में डुप्लिकेट को हटाने का सबसे तेज़/एक-लाइनर तरीका क्या है: मान, या किसी विधि से लौटाया गया परिणाम?रुबी ऐरे में डुप्लिकेट (कुंजी द्वारा) को हटाने के लिए सबसे तेज़/एक-लाइनर तरीका?

उदाहरण के लिए, मेरे पास 20 एक्सएमएल एलिमेंट नोड्स हैं जो सभी समान नाम हैं, लेकिन उनके पास अलग-अलग "टेक्स्ट" मान हैं, जिनमें से कुछ डुप्लिकेट हैं। मैं डुप्लीकेट को "if element.text == last_element.text कहकर हटा दूंगा, इसे हटा दें"। मैं रूबी में कोड की सबसे छोटी राशि में ऐसा कैसे करूं?

मैंने देखा है कि सरल स्ट्रिंग/पूर्णांक मानों के लिए इसे कैसे किया जाए, लेकिन वस्तुओं के लिए नहीं।

+0

साथ backports उपयोग कर सकते हैं एक आधुनिक धारणा के लिए मेरा उत्तर देखें। –

उत्तर

14

यहां मानक हैश तरीका है। ||= ऑपरेटर का उपयोग ध्यान दें, जो a = b unless a लिखने के लिए एक अधिक सुविधाजनक (a ||= b) तरीका है।

array.inject({}) do |hash,item| 
    hash[item.text]||=item 
    hash 
end.values.inspect 

आप इसे एक ही पंक्ति में कर सकते हैं।

स्क्रिप्ट को text तारों की ओ (एन) समानता जांच की आवश्यकता है। जब आप हैश देखते हैं तो ओ (एन) के तहत यही शामिल है।

+0

बिल्कुल तेज़ नहीं है, क्योंकि यह ओ (एन^2) समय में चलता है। फिर फिर यह वास्तव में महत्वपूर्ण नहीं है कि अब सीपीयू का समय कितना सस्ता है। – EmFi

+1

@EmFi, हैश तालिका तक पहुंचने से ओ (एन) नहीं लेता है (हमें स्ट्रिंग 'टेक्स्ट' को फिर से चालू करना चाहिए, लेकिन हमें इसे वैसे भी करना होगा)। मैंने अभी इस मामले के बारे में एक उत्तर पोस्ट किया है: http://stackoverflow.com/questions/1590405/distinguishing-extra-element-from-two-arrays/1590536#1590536 –

+0

@ पावेल क्षमा करें, आप सही हैं। मुझे यह सोचने में एक दूसरे के लिए भ्रमित हो गया कि अतिरिक्त मूल्य कॉल ने इसे ओ (एन^2) बनाया है। जब यह सिर्फ ओ (2 एन) बनाता है। – EmFi

10

यह यह सब करता है:

Hash[*a.map{|x| [x.text, x]}].values 

कम? हां।

(तारांकन वैकल्पिक है; 1.8.6 के लिए आवश्यक प्रतीत होता है)।

उदाहरण के लिए:

a = [Thing.new('a'), Thing.new('b'), Thing.new('c'), Thing.new('c')] 
=> [#<Thing a>, #<Thing b>, #<Thing c>, #<Thing c>] 

Hash[a.map{|x| [x.text, x]}].values 
=> [#<Thing a>, #<Thing b>, #<Thing c>] 

बोरिंग हिस्सा: एक ब्लॉक के साथ

class Thing 
    attr_reader :text 
    def initialize(text) 
    @text = text 
    end 

    def inspect 
    "#<Thing #{text}>" 
    end 
end 
+0

यह वास्तव में अच्छा है, वह क्या है (&: आखिरी)? –

+0

यह नए, यहां तक ​​कि छोटे, सरल संस्करण :) में चला गया है। हालांकि, 'ary.map {| x | कह रहा है x.last} 'और' ary.map (&: last) 'समकक्ष हैं। – Peter

+0

मेरे पास निम्न त्रुटि है: '[]' में: हैश (ArgumentError) के लिए तर्कों की विषम संख्या –

4

उपयोग Array#uniq: यहां थोड़ा परीक्षण वर्ग मैं प्रयोग किया जाता है। आपके मामले में:

array.uniq(&:text) # => array with duplicated `text` removed 

यह रूबी 1.9.2 में पेश किया गया था, तो किसी पुराने संस्करण का उपयोग कर, तो आप require 'backports/1.9.2/array/uniq'

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

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