2011-10-06 8 views
12

के इस उदाहरण लेते हैं:रुबी 1.9 में ऑर्डर किए गए हैश का केवल एक सबसेट कैसे प्राप्त करें?

d = {"a" => 1, "b" => 2, "c" => 3, "d" => 4} 

के बाद से हैश अब आदेश दिया जाता है, मैं a से b करने के लिए या c से d लिए डेटा प्राप्त करना चाहते हो सकता है। समस्या यह है कि मैं d[0..1] या d[2..3] नहीं कर सकता।

मैं तथापि कर सकता है:

irb > d.to_a[0..1] 
=> [["a", 1], ["b", 2]] 

... लेकिन यह गन्दा लगता है और मैं इस तरह के ऑपरेशन के लिए मेरे हैश कास्ट करने के लिए नहीं करना चाहती।

क्या इसे संभालने के लिए कोई क्लीनर समाधान है?

# Holy Grail 
irb > d[0..1] 
=> {"a" => 1, "b" => 2} 

मैं देख सकता हूँ अपने आप को इस तरह के एक विधि कार्यक्रम के लिए कैसे, लेकिन वहाँ कुछ देशी पहले से ही किया है कि मैं इस्तेमाल कर सकते हैं हो सकता है ...?

+0

एक सीमा भी, एक वैध हैश कुंजी हो सकता है तो आप इस के लिए एक कस्टम विधि का उपयोग करना होगा। मुझे नहीं लगता कि अंतर्निहित कुछ भी नहीं है, बीटीडब्ल्यू। – tokland

उत्तर

7

वैसे आप कर सकता है:

> a = {"a" => 1, "b" => 2, "c" => 3, "d" => 4} 
> a.slice(*a.keys[0..1]) 
=> {"a" => 1, "b" => 1} 

कम से कम हैश डाली नहीं है, लेकिन यह अभी भी मेरी राय में बहुत ही सुंदर नहीं है।

+0

यदि आप इसे हैश पर पैच किए गए किसी प्रकार की विधि में बस लपेटते हैं तो यह अधिक सुरुचिपूर्ण होगा। – tadman

+0

मुझे यह समाधान पसंद है ^^ – marcgg

+0

यह एक अच्छा तरीका है, लेकिन आपको अभी भी हैश की सभी चाबियाँ मिलनी हैं। लेकिन अगर कार्यान्वयन इंडेक्स द्वारा हैश को टुकड़ा करने का समर्थन नहीं करता है तो कुछ बेहतर खोजना मुश्किल है। – tokland

4

यदि आप सबसेट का चयन करने के लिए कुंजी पर तुलना करना चाहते हैं, तो आप Hash#select का उपयोग कर सकते हैं, यह 1.8.7 में भी काम करता है लेकिन इसके बजाय सरणी की सरणी देता है (आपके उदाहरण के अनुसार)।

d.select {|k, v| k < 'c' } # => {"a"=>1, "b"=>2} 
d.select {|k, v| k < 'c' } # 1.8.7 => [["a", 1], ["b", 2]] 

तुम भी प्रदान की आप पहले से ही कुंजी आप चाहते हैं पता ActiveSupport के हैश विस्तार है कि एक slice method to Hash कि यह भी काम कर सकते हैं कहते हैं, का उपयोग कर सकते हैं।

require 'active_support/core_ext/hash/slice' 
d.slice('a', 'b') # => {"a"=>1, "b"=>2} 
+0

इस मामले में ओपी सभी विकल्पों के साथ हैश # slice_by_index चाहता है जो Array # [] का समर्थन करता है। – tokland

+0

हां, ज्यादातर समय, आप जानते हैं कि आप चाहते हैं कि चाबियाँ या तुलना के आधार पर उन्हें कैसे चुनना है, लेकिन वह उन्हें इंडेक्स पर आधारित करना चाहता है, जो मैंने जवाब नहीं दिया है। इसके शीर्ष पर, मेरा उत्तर खराब है क्योंकि यह ActiveSupport का उपयोग करता है जहां @DuoSRX दिखाया गया है, केवल हैश # value_at की आवश्यकता है। –

+0

@BiHi मेरी स्थिति में मैं अपनी अनुक्रमणिका के आधार पर चाबियाँ प्राप्त करना चाहता हूं, न कि उनके मूल्य – marcgg

2

शायद वहाँ यह करने के लिए एक बेहतर तरीका है, लेकिन यह एक विचार है:

class Hash 
    def slice_by_index(a, b = nil) 
     k = if a.is_a?(Range) 
      keys[a] 
     elsif b.nil? 
      [keys[a]] 
     else 
      keys[a,b] 
     end 
     k.inject({}){|h, k| h[k] = self[k] ; h } 
    end 
end 

h = {"a" => 1, "b" => 2, "c" => 3, "d" => 4} 
p h.slice_by_index(1..3) #range 
p h.slice_by_index(2) #single element 
p h.slice_by_index(0,3) #start, lenght 
संबंधित मुद्दे