रूबी में हैश कीज़ के रूप में प्रतीकों का उपयोग क्यों करें?


162

बहुत बार लोग रूबी हैश में प्रतीकों का उपयोग चाबियों के रूप में करते हैं।

स्ट्रिंग का उपयोग करने पर क्या फायदा है?

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

hash[:name]

बनाम

hash['name']

जवाबों:


227

टी एल; डॉ:

प्रतीकों का उपयोग न केवल तुलना करते समय समय बचाता है, बल्कि स्मृति को भी बचाता है, क्योंकि वे केवल एक बार संग्रहीत होते हैं।

रूबी प्रतीक अपरिवर्तनीय हैं (बदला नहीं जा सकता), जो कुछ को बहुत आसान लग रहा है

लघु (ish) उत्तर:

प्रतीकों का उपयोग न केवल तुलना करते समय समय बचाता है, बल्कि स्मृति को भी बचाता है, क्योंकि वे केवल एक बार संग्रहीत होते हैं।

रूबी में प्रतीक मूल रूप से "अपरिवर्तनीय स्ट्रिंग्स" हैं .. इसका मतलब है कि उन्हें बदला नहीं जा सकता है, और इसका मतलब है कि आपके स्रोत कोड में कई बार संदर्भित होने पर समान प्रतीक, हमेशा एक ही इकाई के रूप में संग्रहीत किया जाता है, जैसे कि एक ही ऑब्जेक्ट आईडी है ।

दूसरी ओर तार परस्पर भिन्न होते हैं , इन्हें कभी भी बदला जा सकता है। इसका तात्पर्य है कि रूबी को आपके प्रत्येक स्रोत कोड में आपके द्वारा उल्लिखित प्रत्येक स्ट्रिंग को अलग इकाई में संग्रहीत करने की आवश्यकता है, उदाहरण के लिए यदि आपके पास एक स्ट्रिंग "नाम" है जो आपके स्रोत कोड में कई बार उल्लिखित है, तो रूबी को इन सभी को अलग-अलग स्ट्रिंग ऑब्जेक्ट्स में संग्रहीत करने की आवश्यकता है, क्योंकि वे बाद में बदल सकता है (यह रूबी स्ट्रिंग की प्रकृति है)।

यदि आप एक हैश कुंजी के रूप में एक स्ट्रिंग का उपयोग करते हैं, तो रूबी को स्ट्रिंग का मूल्यांकन करने और इसकी सामग्री को देखने की आवश्यकता होती है (और उस पर एक हैश फ़ंक्शन की गणना करें) और उन हैश के मूल्यों के विरुद्ध परिणाम की तुलना करें जो पहले से ही हैश में संग्रहीत हैं। ।

यदि आप किसी हैश कुंजी के रूप में एक प्रतीक का उपयोग करते हैं, तो यह निहित है कि यह अपरिवर्तनीय है, इसलिए रूबी मूल रूप से (हैशेड) ऑब्जेक्ट (-शेड) ऑब्जेक्ट के-आईडी (हैश) ऑब्जेक्ट-आईडी के खिलाफ तुलना कर सकती है जो पहले से ही संग्रहीत हैं द हैश। (काफी तेज)

डाउनसाइड: प्रत्येक प्रतीक रूबी दुभाषिया के प्रतीक-तालिका में एक स्लॉट का उपभोग करता है, जो कभी जारी नहीं होता है। प्रतीक कभी भी कचरा एकत्र नहीं होते हैं। तो एक कोने-केस तब होता है जब आपके पास बड़ी संख्या में प्रतीक होते हैं (जैसे ऑटो-जनरेट किए गए)। उस स्थिति में आपको मूल्यांकन करना चाहिए कि यह आपके रूबी दुभाषिया के आकार को कैसे प्रभावित करता है।

टिप्पणियाँ:

यदि आप स्ट्रिंग तुलना करते हैं, तो रूबी प्रतीकों का केवल उनकी वस्तु आईडी से तुलना कर सकती है, उनका मूल्यांकन किए बिना। यह तार की तुलना में बहुत तेज है, जिसका मूल्यांकन करने की आवश्यकता है।

यदि आप एक हैश का उपयोग करते हैं, तो रूबी हमेशा आपके द्वारा उपयोग की जाने वाली कुंजी से "हैश-कुंजी" की गणना करने के लिए एक हैश-फ़ंक्शन लागू करती है। आप एमडी 5-हैश की तरह कुछ कल्पना कर सकते हैं। और फिर रूबी उन "हैशेड कीज़" की एक दूसरे से तुलना करती है।

लंबा जवाब:

https://web.archive.org/web/20180709094450/http://www.reactive.io/tips/2009/01/11/the-difference-between-ruby-symbols-and-strings

http://www.randomhacks.net.s3-website-us-east-1.amazonaws.com/2007/01/20/13-ways-of-looking-at-a-ruby-symbol/


5
फ़िबी, प्रतीक रूबी के अगले संस्करण में GCd होंगे
Ajedi32

2
इसके अलावा, रूबी में हैश कीज़ के रूप में उपयोग किए जाने पर स्ट्रिंग्स स्वचालित रूप से जमे हुए हैं। इसलिए यह बिल्कुल सच नहीं है कि इस संदर्भ में उनके बारे में बात करते समय स्ट्रिंग्स परस्पर हैं।
Ajedi32

1
विषय पर महान अंतर्दृष्टि और "लंबे उत्तर" अनुभाग में पहला लिंक हटा दिया जाता है या माइग्रेट किया जाता है।
हबसागर १३

2
रूबी 2.2 में
मार्क

2
बहुत बढ़िया जवाब! ट्रोलिंग पक्ष पर, आपका "संक्षिप्त उत्तर" भी काफी लंबा है। ;)
टेक्नोफाइल

22

इसका कारण दक्षता है, एक स्ट्रिंग पर कई लाभ के साथ:

  1. प्रतीक अपरिवर्तनीय हैं, इसलिए प्रश्न "यदि परिवर्तन होता है तो क्या होता है?" पूछने की जरूरत नहीं है।
  2. स्ट्रिंग्स आपके कोड में डुप्लिकेट हैं और आमतौर पर मेमोरी में अधिक स्थान ले लेंगे।
  3. हैश लुकअप की तुलना करने के लिए कुंजियों के हैश की गणना करनी चाहिए। यह O(n)स्ट्रिंग्स के लिए है और प्रतीकों के लिए स्थिर है।

इसके अलावा, रूबी 1.9 ने सिंबल सिंटैक्स को केवल हैश कीज़ (जैसे h.merge(foo: 42, bar: 6)) के साथ पेश किया, और रूबी 2.0 में कीवर्ड तर्क हैं जो केवल सिम्बल कीज़ के लिए काम करते हैं।

नोट :

1) आपको यह जानकर आश्चर्य हो सकता है कि रूबी Stringकिसी भी अन्य प्रकार की तुलना में कुंजियों का अलग तरह से व्यवहार करती है । वास्तव में:

s = "foo"
h = {}
h[s] = "bar"
s.upcase!
h.rehash   # must be called whenever a key changes!
h[s]   # => nil, not "bar"
h.keys
h.keys.first.upcase!  # => TypeError: can't modify frozen string

केवल स्ट्रिंग कुंजी के लिए, रूबी ऑब्जेक्ट के बजाय एक जमे हुए प्रतिलिपि का उपयोग करेगा।

2) अक्षर "बी", "ए", और "आर" केवल :barएक कार्यक्रम में होने वाली सभी घटनाओं के लिए केवल एक बार संग्रहीत किए जाते हैं । रूबी 2.2 से पहले, यह लगातार नया बनाने के लिए एक बुरा विचार था जिसका Symbolsकभी भी पुन: उपयोग नहीं किया गया था, क्योंकि वे वैश्विक प्रतीक खोज तालिका में हमेशा के लिए बने रहेंगे। रूबी 2.2 कचरा इकट्ठा करेगा, इसलिए कोई चिंता नहीं है।

3) वास्तव में, एक प्रतीक के लिए हैश की गणना रूबी 1.8.x में किसी भी समय नहीं हुई, क्योंकि ऑब्जेक्ट आईडी का उपयोग सीधे किया गया था:

:bar.object_id == :bar.hash # => true in Ruby 1.8.7

रूबी 1.9.x में, यह एक सत्र से दूसरे सत्र में हैश परिवर्तन के रूप में बदल गया है (उन सहित Symbols)

:bar.hash # => some number that will be different next time Ruby 1.9 is ran

अपने उत्कृष्ट नोटों के लिए +1! मैंने मूल रूप से अपने उत्तर में हैश फ़ंक्शन का उल्लेख नहीं किया, क्योंकि मैंने इसे पढ़ने में आसान बनाने की कोशिश की :) :)
तिलो

@Tilo: वास्तव में, यही कारण है कि मैंने अपना उत्तर लिखा है :-) मैंने सिर्फ रूबी 1.9 में विशेष वाक्यविन्यास का उल्लेख करने के लिए अपना उत्तर संपादित किया है और रूबी 2.0 के
प्रस्तावित

क्या आप समझा सकते हैं कि स्ट्रिंग्स के लिए सिंबल और O (n) के लिए हेश लुकिंग कैसे स्थिर हैं?
असद मूसवी

7

पुन :: एक स्ट्रिंग का उपयोग करने पर क्या फायदा है?

  • स्टाइलिंग: इसका रूबी-तरीका है
  • (बहुत) थोड़ा तेज मान देखने के बाद से एक प्रतीक हैशिंग के बराबर है एक स्ट्रिंग बनाम हैशिंग के बराबर हैशिंग के बराबर है।

  • नुकसान: कार्यक्रम के प्रतीक तालिका में एक स्लॉट का उपभोग करता है जो कभी जारी नहीं होता है।


4
+1 यह उल्लेख करने के लिए कि प्रतीक कभी कचरा एकत्र नहीं किया गया है।
वोर्टिको

प्रतीक कभी कचरा एकत्र नहीं किया जाता है - रूबी 2.2+ से सत्य नहीं है
यूडिमोनिया

0

मैं रूबी 2.x में शुरू किए गए जमे हुए तारों के बारे में अनुवर्ती कार्रवाई करना चाहूंगा।

जब आप एक पाठ इनपुट से आने वाले कई तारों से निपटते हैं (मैं HTTP पैरा या पेलोड के बारे में सोच रहा हूं, रैक के माध्यम से, उदाहरण के लिए), तो हर जगह तार का उपयोग करना आसान है।

जब आप उनमें से दर्जनों के साथ सौदा करते हैं, लेकिन वे कभी नहीं बदलते हैं (यदि वे आपके व्यवसाय "शब्दावली" हैं), तो मुझे लगता है कि उन्हें ठंड से फर्क पड़ सकता है। मैंने अभी तक कोई बेंचमार्क नहीं किया है, लेकिन मुझे लगता है कि यह प्रतीकों के प्रदर्शन को बंद कर देगा।

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