रूबी में हैश को सॉर्ट करें, रूबी में हैश लौटें


257

क्या यह हैश को सॉर्ट करने और हैश ऑब्जेक्ट (एरे के बजाय) को वापस करने का सबसे अच्छा तरीका होगा:

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

Hash[h.sort]
# => {"a"=>1, "b"=>2, "c"=>3, "d"=>4}

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

रूबी 1.9 में भी समझ में आता है। मेरे पास db से आने वाली तारीखों (चाबियों के रूप में) के आधार पर नियुक्त नियुक्तियों का एक संग्रह था और मैं स्वयं माणिक के माध्यम से छांटा गया था। उदाहरण के लिए। {"2012-09-22": [...], "2012-09-30": [...], "2012-10-12": [...]}
आदित सक्सेना

हां, मुझे लगता है कि आपकी हैश [h.sort] सॉर्टिंग कुंजी की तुलना में अधिक प्रभावी है और फिर हैश को सॉर्ट किया गया है।
डगलस


3
आपके समाधान के बारे में सोचने के लिए आपके पास कुछ साल हैं, क्या आप एक उत्तर स्वीकार करने के लिए तैयार हैं? ;-)
मार्क थॉमस

जवाबों:


219

रूबी 2.1 में यह सरल है:

h.sort.to_h

@zachaysan लेकिन यह काम करता है: h.sort{|a,z|a<=>z}.to_h(2.1.10 परीक्षण किया है, 2.3.3)
whitehat101

@ whitehat101 आप सही हैं। मेरे पास एक बग था ( aएक सरणी है, न केवल कुंजी)। मैंने अपनी टिप्पणी हटा दी है।
zachaysan

बस किसी और मामले में हैश की एक सरणी को सॉर्ट करने के तरीके की तलाश में है, यह चाल (जहां एच सरणी है) कर देगा h.map(&:sort).map(&:to_h):।
जेएम जेजेन

82

नोट: रूबी> = 1.9.2 में एक ऑर्डर-प्रोटेक्टिंग हैश है: जो ऑर्डर कीज़ डाले गए हैं, वे उसी क्रम में होंगे जो वे एनुमरेटेड हैं। नीचे पुराने संस्करणों या पिछड़े-संगत कोड पर लागू होता है।

क्रमबद्ध हैश की कोई अवधारणा नहीं है। तो नहीं, आप जो कर रहे हैं वह सही नहीं है।

यदि आप इसे प्रदर्शन के लिए क्रमबद्ध करना चाहते हैं, तो एक स्ट्रिंग लौटाएँ:

"{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"

या, यदि आप क्रम में चाबियाँ चाहते हैं:

h.keys.sort

या, यदि आप तत्वों को क्रम में पहुँचाना चाहते हैं:

h.sort.map do |key,value|
  # keys will arrive in order to this block, with their associated value.
end

लेकिन सारांश में, यह हैश के बारे में बात करने के लिए कोई मतलब नहीं है। से डॉक्स , "जिस क्रम में आप या तो कुंजी या मान से एक हैश पार मनमाने ढंग से लग सकता है, और आम तौर पर प्रविष्टि क्रम में नहीं होगा।" तो हैश में एक विशिष्ट क्रम में चाबियाँ डालने से मदद नहीं मिलेगी।


यह सही है। मैं रूबी में आदेशित कार्यक्षमता प्राप्त करने के लिए RBtree रत्न का उपयोग करने का सुझाव दूंगा।
एरोन स्क्रैग्स

26
1.9.2 हैश डालने का क्रम शुरू किया जाएगा। Redmine.ruby-lang.org/issues/show/994
डेविड

4
"1.9.2 हैश डालने का क्रम शुरू किया जाएगा।", और यह मीठा है।
को टिन मैन

2
मेरी पहली टिप्पणी (मजाकिया लग रहा है): उदाहरण के लिए, हैश ऑर्डर पर भरोसा करना चुपचाप और अप्रत्याशित रूप से रूबी संस्करणों के लिए 1.9.2 से अधिक पुराना होना चाहिए।
जो लिस

5
यह उत्तर ओपी प्रश्न के दो भागों में से एक के भी उत्तर के बिना लगभग 20 + 1 कैसे नहीं मिला? "1) क्या वह (ओपी उदाहरण) हैश को क्रमबद्ध करने का सबसे अच्छा तरीका होगा, 2) और हैश ऑब्जेक्ट लौटाएगा"? मैंने ईर्ष्या नहीं की + 1 की :) यह सिर्फ उस उत्तर को पढ़ने के बाद है जिसे मैं अभी भी मूल प्रश्नों के साथ छोड़ रहा हूं। इसके अलावा अगर बिंदु यह है कि इस प्रश्न के उत्तर के लिए टिप्पणियों के जवाब के लिए छांटे गए हैश जैसी कोई चीज नहीं है, तो इस सवाल का जवाब stackoverflow.com/questions/489139/…
jj_

64

मैंने हमेशा उपयोग किया है sort_by#sort_byआउटपुट को Hash[]हैश बनाने के लिए आपको आउटपुट को लपेटने की आवश्यकता होती है , अन्यथा यह सरणी का एक आउटपुट देता है। वैकल्पिक रूप से, इसे पूरा करने के लिए आप #to_hट्यूपल्स की सरणी पर विधि को एक k=>vसंरचना (हैश) में बदलने के लिए चला सकते हैं ।

hsh ={"a" => 1000, "b" => 10, "c" => 200000}
Hash[hsh.sort_by{|k,v| v}] #or hsh.sort_by{|k,v| v}.to_h

इसी तरह का प्रश्न है " संख्या मान द्वारा रूबी हैश कैसे छांटें? "।


8
sort_byहैश पर उपयोग करने से एक सरणी वापस आ जाएगी। आपको इसे फिर से हैश के रूप में मैप करना होगा। Hash[hsh.sort_by{|k,v| v}]
स्टीवंसपिल


3
राइट, सॉर्ट मानों पर है hsh.sort_by(&:last).to_h => {"b"=>10, "a"=>1000, "c"=>200000}:।
Cary Swoveland

1
ध्यान दें कि कॉलिंग to_hकेवल रूबी 2.1.0+ में समर्थित है
फ्रॉग्ज़

1
टिप्पणी में एक टाइपो है, सुधार:sort_by{|k,v| v}.to_h)
घबराना

13

नहीं, यह नहीं है (रूबी 1.9.x)

require 'benchmark'

h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
many = 100_000

Benchmark.bm do |b|
  GC.start

  b.report("hash sort") do
    many.times do
      Hash[h.sort]
    end
  end

  GC.start

  b.report("keys sort") do
    many.times do
      nh = {}
      h.keys.sort.each do |k|
        nh[k] = h[k]
      end
    end
  end
end

       user     system      total        real
hash sort  0.400000   0.000000   0.400000 (  0.405588)
keys sort  0.250000   0.010000   0.260000 (  0.260303)

बड़े हैश अंतर के लिए 10x और अधिक तक बढ़ेगा


12

आपने ओपी में अपने आप को सबसे अच्छा जवाब दिया: Hash[h.sort]यदि आप अधिक संभावनाओं के लिए तरसते हैं, तो यहां मूल हैश को संशोधित करने के लिए जगह बनाई गई है:

h.keys.sort.each { |k| h[k] = h.delete k }

1
जिज्ञासु के लिए, यह रूबी 1.9.3 पर stackoverflow.com/a/17331221/737303 में "कुंजियों की तरह" की तुलना में थोड़ा तेज चलता है ।
नाइट्रोजन

9

द्वारा क्रमबद्ध हैश कुंजी , रूबी में वापसी हैश

साथ destructuring और हैश # प्रकार

hash.sort { |(ak, _), (bk, _)| ak <=> bk }.to_h

गणनीय # sort_by

hash.sort_by { |k, v| k }.to_h

डिफ़ॉल्ट व्यवहार के साथ # सॉर्ट करें

h = { "b" => 2, "c" => 1, "a" => 3  }
h.sort         # e.g. ["a", 20] <=> ["b", 30]
hash.sort.to_h #=> { "a" => 3, "b" => 2, "c" => 1 }

नोट: <रूबी 2.1

array = [["key", "value"]] 
hash  = Hash[array]
hash #=> {"key"=>"value"}

नोट:> रूबी 2.1

[["key", "value"]].to_h #=> {"key"=>"value"}

1
यदि vआप का उपयोग नहीं कर रहे हैं तो एक अंडरस्कोर उपसर्ग करना चाहिएhash.sort_by { |k, _v| k }.to_h
सिल्वा 96

6

ActiveSupport :: यदि आप माणिक 1.9.2 का उपयोग नहीं करना चाहते हैं या अपना वर्कअराउंड रोल नहीं करना चाहते हैं, तो आर्डरहैड एक और विकल्प है।


लिंक टूटा है
स्नेक सैंडर्स

3
मैंने Google को इंगित करने के लिए लिंक को ठीक किया, यदि कोई इतिहासकार यह शोध करना चाहता है कि यह अतीत में कैसे किया जा सकता था। लेकिन अब इस पर आने वाले किसी भी व्यक्ति को रूबी के हालिया संस्करण का उपयोग करना चाहिए।
संन्यासी


0

मुझे भी यही समस्या थी (मुझे अपने उपकरणों को उनके नाम से क्रमबद्ध करना पड़ा) और मैंने इस तरह हल किया:

<% @equipments.sort.each do |name, quantity| %>
...
<% end %>

@ उपकरण एक हैश है जो मैं अपने मॉडल पर बनाता हूं और अपने नियंत्रक पर लौटता हूं। यदि आप कॉल करते हैं। तो यह कुंजी मूल्य के आधार पर हैश को सॉर्ट करेगा।


-3

मुझे पहले वाली पोस्ट में समाधान पसंद आया।

मैंने एक मिनी-क्लास बनाया, इसे बुलाया class AlphabeticalHash। इसकी एक विधि भी है ap, जो एक तर्क, Hashइनपुट के रूप में स्वीकार करती है ap variable:। अकिन से पीपी ( pp variable)

लेकिन यह वर्णमाला सूची (इसकी कुंजी) में प्रिंट (कोशिश और) करेगा। डनो अगर कोई और इसका उपयोग करना चाहता है, तो यह एक रत्न के रूप में उपलब्ध है, आप इसे इस तरह से स्थापित कर सकते हैं:gem install alphabetical_hash

मेरे लिए, यह काफी सरल है। यदि दूसरों को अधिक कार्यक्षमता की आवश्यकता है, तो मुझे बताएं, मैं इसे मणि में शामिल करूंगा।

EDIT: इसका श्रेय पीटर को जाता है , जिन्होंने मुझे यह विचार दिया। :)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.