2010-07-18 17 views
57

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

  • संरचना अच्छी तरह से क्या कर सकती है?
  • क्या कुछ भी संरचना कर सकती है, हैश नहीं कर सकता है?

googling के बाद, संरचना की अवधारणा सी में महत्वपूर्ण है, लेकिन मैं सी

के बारे में ज्यादा पता नहीं है

उत्तर

75

Structs (अलावा कैसे कोड लग रहा है करने के लिए) को निम्न तरीकों से HashMaps का उपयोग कर से अलग:

  • एक struct, विशेषताओं का एक निश्चित सेट है, जबकि आप एक हैश को नई चाबी जोड़ें।
  • एक विशेषता को कॉल करना जो किसी स्ट्रक्चर के उदाहरण पर मौजूद नहीं है, कोई हैशूटर त्रुटि का कारण बनता है, जबकि हैश से मौजूद एक मौजूदा कुंजी के लिए मान प्राप्त करने से शून्य हो जाएगी।
  • अलग-अलग structs के दो उदाहरण कभी भी समान नहीं होंगे, भले ही structs के समान गुण हों और उदाहरणों के समान मान हों (यानी Struct.new(:x).new(42) == Struct.new(:x).new(42) गलत है, जबकि Foo = Struct.new(:x); Foo.new(42)==Foo.new(42) सत्य है)।
  • structs के लिए to_a विधि मूल्यों की एक सरणी देता है, जबकि to_a एक हैश पर आप की-वैल्यू-जोड़े की एक सरणी (जहां "जोड़ी" का अर्थ है "दो तत्व सरणी")
  • आप कर सकते हैं Foo = Struct.new(:x, :y, :z) हो जाता है Foo.new(1,2,3) विशेषता नामों का स्पेल किए बिना Foo का उदाहरण बनाने के लिए।

तो प्रश्न का उत्तर देने के लिए: जब आप गुणों के ज्ञात सेट के साथ ऑब्जेक्ट्स मॉडल करना चाहते हैं, तो structs का उपयोग करें। जब आप अनियंत्रित उपयोग हैशैप्स मॉडल करना चाहते हैं (उदाहरण के लिए गिनती है कि प्रत्येक शब्द स्ट्रिंग या मैपिंग उपनामों में पूर्ण नाम आदि में कितनी बार होता है, निश्चित रूप से किसी संरचना के लिए नौकरियां नहीं होती हैं, जबकि किसी व्यक्ति को नाम, उम्र और पता वाला मॉडल बनाना होगा Person = Struct.new(name, age, address) के लिए एकदम सही फिट)।

एक sidenote के रूप में: सी structs रूबी structs के साथ कुछ भी करने के लिए कुछ भी नहीं है, तो अपने आप को भ्रमित होने मत देना।

+0

आपका अन्य बिंदुओं सभी सही (ताकि के लिए +1) हैं, लेकिन [ 'Struct # == '] (http://ruby-doc.org/core/classes/Struct.html#M000890) जब आप वास्तव में' Struct.new' के परिणाम को संग्रहीत करते हैं, तो इसे दो बार कॉल करने के विरोध में आपने जो समझाया है उससे भिन्न रूप से काम करता है एक ही तर्क। –

+0

@ मार्ककशकॉफ: अगर मैं 'Foo = Struct.new (: x) करता हूं; बार = स्ट्रक्चर.न्यू (: एक्स) 'और फिर' Foo.new (42) == बार। नया (42) 'मैं झूठा हो जाऊंगा। अगर मैं 'Foo.new (42) == Foo.new (42) करता हूं' मैं सच हो जाऊंगा। और यदि आप ध्यान से पढ़ते हैं, तो वही है जो मैंने कहा (* अलग * structs के दो उदाहरण ")। – sepp2k

+0

मुझे लगता है कि आपका क्या मतलब है। यह मुझे स्पष्ट नहीं था क्योंकि आपने इसे एक स्पष्टीकरण के विपरीत नहीं किया था कि समानता काम करती है एक ही स्ट्रक्चर प्रकार का उपयोग करते समय अपेक्षित। –

9

Struct प्रलेखन से:

एक संरचना करने के लिए एक सुविधाजनक तरीका है एक स्पष्ट वर्ग लिखने के बिना, एक्सेसर विधियों का उपयोग करके, कई विशेषताओं को एक साथ बंडल करें।

दूसरी ओर, एक Hash:

एक हैश कुंजी-मान जोड़ों का एक संग्रह है। यह एक ऐरे के समान है, सिवाय इसके कि अनुक्रमण किसी भी ऑब्जेक्ट प्रकार की मनमानी कुंजी के माध्यम से किया जाता है, एक पूर्णांक सूचकांक नहीं। जिस क्रम में आप किसी भी कुंजी या मूल्य से हैश को पार करते हैं, वह मनमाने ढंग से प्रतीत होता है, और आमतौर पर सम्मिलन आदेश में नहीं होगा।

मुख्य अंतर यह है कि आप अपने डेटा तक कैसे पहुंचते हैं।

ruby-1.9.1-p378 > Point = Struct.new(:x, :y) 
=> Point 
ruby-1.9.1-p378 > p = Point.new(4,5) 
=> #<struct Point x=4, y=5> 
ruby-1.9.1-p378 > p.x 
=> 4 
ruby-1.9.1-p378 > p.y 
=> 5 
ruby-1.9.1-p378 > p = {:x => 4, :y => 5} 
=> {:x=>4, :y=>5} 
ruby-1.9.1-p378 > p.x 
NoMethodError: undefined method `x' for {:x=>4, :y=>5}:Hash 
    from (irb):7 
    from /Users/mr/.rvm/rubies/ruby-1.9.1-p378/bin/irb:17:in `<main>' 
ruby-1.9.1-p378 > p[:x] 
=> 4 
ruby-1.9.1-p378 > p[:y] 
=> 5 

संक्षेप में, आप एक नया Struct होगा जब आप एक वर्ग है कि एक "plain old data" structure (वैकल्पिक अधिक तरीकों के साथ यह विस्तार के इरादे के साथ) है चाहते हैं, और यदि आप एक हैश का उपयोग जब आप एक की जरूरत नहीं है जाएगा औपचारिक प्रकार बिल्कुल।

33

मुझे पता है कि यह सवाल लगभग अच्छी तरह से उत्तर दिया गया था, लेकिन आश्चर्य की बात है कि किसी ने भी सबसे बड़ा अंतर और Struct के वास्तविक लाभों में से किसी एक के बारे में बात नहीं की है। और मुझे लगता है कि यही कारण है कि somebody is still asking

मैं अंतर को समझने, लेकिन, एक हैश पर एक Struct का उपयोग करते समय एक हैश एक ही बात कर सकते हैं, और से निपटने के लिए आसान है करने के लिए वास्तविक लाभ क्या है? ऐसा लगता है जैसे स्ट्रक्चर अनावश्यक हैं।

Structतेजी है।

require 'benchmark' 

Benchmark.bm 10 do |bench| 
    bench.report "Hash: " do 
    50_000_000.times do { name: "John Smith", age: 45 } end 
    end 

    bench.report "Struct: " do 
    klass = Struct.new(:name, :age) 
    50_000_000.times do klass.new("John Smith", 45) end 
    end 

end 

# ruby 2.2.2p95 (2015-04-13 revision 50295) [x64-mingw32]. 
#     user  system  total  real 
# Hash:  22.340000 0.016000 22.356000 (24.260674) 
# Struct:  12.979000 0.000000 12.979000 (14.095455) 

# ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin11.0] 
# 
#     user  system  total  real 
# Hash:  31.980000 0.060000 32.040000 (32.039914) 
# Struct:  16.880000 0.010000 16.890000 (16.886061) 
+3

का उपयोग कर सकते हैं शायद यह ब्याज की बात है: मैं सिग्विन रूबी (2.2.3p173) के साथ एक बार अपने बेंचमार्क को दोबारा शुरू करता हूं और हश और 1 9 .8575 के लिए उपयोगकर्ता के समय 62.462 के लिए मिलता है। फिर मैंने इसे जेवीबी 1.7.23 के साथ जेवीएम 1.7 पर दोबारा शुरू किया और हैश के लिए 8.401 और स्ट्रक्चर के लिए 8.701 मिला। जबकि रूबी पर गति का लाभ बड़ा है, दोनों में जरुबी के तहत एक ही गति है। – user1934428

+0

मुझे आश्चर्य है कि कम स्मृति का उपभोग करता है। – Nakilon

8

एक और मुख्य अंतर यह है कि आप एक स्ट्रक्चर में व्यवहार विधियों को जोड़ सकते हैं।

Customer = Struct.new(:name, :address) do 

    def greeting; "Hello #{name}!" ; end 

end 

Customer.new("Dave", "123 Main").greeting # => "Hello Dave!" 
+0

मुझे लगता है कि यह एक बड़ा अंतर है जो स्ट्रक्चर बनाम हैश को औचित्य देगा। चूंकि रेल सम्मेलन के बाद आपके पास एक ही रूबी फ़ाइल (ऑटोलोडिंग चिंताओं के कारण) में दो कक्षाएं नहीं होनी चाहिए, कई बार एक वर्ग प्रतिस्थापन बनाने का एक शानदार तरीका है जो प्रस्तुतकर्ता/सजावटी के रूप में कार्य करता है। – sandre89

0

यदि आप डेटा को समाहित करने जा रहे हैं, तो हैश (या हैश का एक ऐरे) ठीक है। आप डेटा में हेरफेर है या अन्य डेटा के साथ बातचीत करने की योजना बना रहे हैं, तो एक संरचना कुछ दिलचस्प संभावनाएं खोल सकते हैं:

Point = Struct.new(:x, :y) 
point_a = Point.new(0,0) 
point_b = Point.new(2,3) 

class Point 
    def distance_to another_point 
    Math.sqrt((self.x - another_point.x)**2 + (self.y - another_point.y)**2) 
    end 
end 

puts point_a.distance_to point_b 
+0

आप 'क्लास प्वाइंट << हैश' कर सकते हैं और सभी एक जैसे होंगे। – Nakilon

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