หลายครั้งที่ผู้คนใช้สัญลักษณ์เป็นกุญแจสำคัญใน Ruby hash
ข้อดีของการใช้สตริงคืออะไร
เช่น:
hash[:name]
เมื่อเทียบกับ
hash['name']
หลายครั้งที่ผู้คนใช้สัญลักษณ์เป็นกุญแจสำคัญใน Ruby hash
ข้อดีของการใช้สตริงคืออะไร
เช่น:
hash[:name]
เมื่อเทียบกับ
hash['name']
คำตอบ:
TL; DR:
การใช้สัญลักษณ์ไม่เพียง แต่ช่วยประหยัดเวลาเมื่อทำการเปรียบเทียบ แต่ยังช่วยประหยัดหน่วยความจำเพราะพวกเขาจะถูกเก็บไว้เพียงครั้งเดียว
สัญลักษณ์ Ruby นั้นไม่เปลี่ยนรูป (ไม่สามารถเปลี่ยนแปลงได้) ซึ่งทำให้การค้นหาง่ายขึ้นมากขึ้น
คำตอบสั้น ๆ (ish):
การใช้สัญลักษณ์ไม่เพียง แต่ช่วยประหยัดเวลาเมื่อทำการเปรียบเทียบ แต่ยังช่วยประหยัดหน่วยความจำเพราะพวกเขาจะถูกเก็บไว้เพียงครั้งเดียว
สัญลักษณ์ในทับทิมนั้นเป็น"สายอักขระที่ไม่เปลี่ยนรูป"ซึ่งหมายความว่าพวกเขาไม่สามารถเปลี่ยนแปลงได้และมันก็หมายความว่าสัญลักษณ์เดียวกันเมื่ออ้างอิงหลายครั้งตลอดทั้งซอร์สโค้ดของคุณจะถูกเก็บไว้เป็นเอนทิตีเดียวกันเสมอเช่นมี id วัตถุเดียวกัน .
สตริงในทางตรงกันข้ามจะไม่แน่นอนพวกเขาสามารถเปลี่ยนแปลงได้ตลอดเวลา นี่หมายความว่า Ruby ต้องการเก็บแต่ละสตริงที่คุณพูดถึงในซอร์สโค้ดของคุณโดยแยกเอนทิตี้เช่นถ้าคุณมีสตริง "ชื่อ" หลายครั้งที่ถูกกล่าวถึงในซอร์สโค้ดของคุณ Ruby จำเป็นต้องเก็บสิ่งเหล่านี้ทั้งหมดในวัตถุสตริงแยกต่างหาก อาจมีการเปลี่ยนแปลงในภายหลัง (นั่นคือลักษณะของสตริงทับทิม)
หากคุณใช้สตริงเป็นคีย์แฮช Ruby จำเป็นต้องประเมินสตริงและดูที่เนื้อหา (และคำนวณฟังก์ชันแฮชบนนั้น) และเปรียบเทียบผลลัพธ์กับค่า (แฮช) ของคีย์ที่เก็บไว้ในแฮชแล้ว .
หากคุณใช้สัญลักษณ์เป็นคีย์แฮชก็หมายความว่ามันไม่เปลี่ยนรูปดังนั้นโดยทั่วไปแล้วทับทิมสามารถทำการเปรียบเทียบ (ฟังก์ชันแฮชของ) object-id กับรหัสวัตถุ (hashed) ที่เก็บไว้ใน แฮช (เร็วกว่ามาก)
ข้อเสีย: สัญลักษณ์แต่ละอันจะใช้ช่องในตารางสัญลักษณ์ของผู้แปล Ruby ซึ่งไม่เคยถูกเปิดเผย สัญลักษณ์จะไม่ถูกเก็บรวบรวมขยะ กรณีมุมคือเมื่อคุณมีสัญลักษณ์จำนวนมาก (เช่นสัญลักษณ์ที่สร้างขึ้นโดยอัตโนมัติ) ในกรณีนี้คุณควรประเมินว่าสิ่งนี้มีผลต่อขนาดของล่าม Ruby ของคุณอย่างไร
หมายเหตุ:
หากคุณทำการเปรียบเทียบสตริง Ruby สามารถเปรียบเทียบสัญลักษณ์โดยรหัสวัตถุของพวกเขาโดยไม่ต้องประเมินพวกเขา เร็วกว่าการเปรียบเทียบสตริงซึ่งต้องได้รับการประเมิน
หากคุณเข้าถึงแฮช Ruby จะใช้ฟังก์ชันแฮชเพื่อคำนวณ "แฮชคีย์" จากคีย์ใด ๆ ก็ตามที่คุณใช้อยู่เสมอ คุณสามารถจินตนาการบางสิ่งบางอย่างเช่น MD5-hash จากนั้นทับทิมจะเปรียบเทียบ "คีย์ที่ถูกแฮช" กับสิ่งอื่น
คำตอบยาว:
เหตุผลก็คือประสิทธิภาพด้วยการได้รับมากกว่าหนึ่งสตริง:
O(n)
สำหรับสตริงและค่าคงที่สำหรับสัญลักษณ์ยิ่งกว่านั้น Ruby 1.9 ยังได้แนะนำไวยากรณ์ที่ง่ายขึ้นสำหรับการแฮชด้วยปุ่มสัญลักษณ์ (เช่นh.merge(foo: 42, bar: 6)
) และ Ruby 2.0 มีอาร์กิวเมนต์ของคำหลักที่ใช้งานได้กับคีย์สัญลักษณ์เท่านั้น
หมายเหตุ :
1) คุณอาจประหลาดใจที่รู้ว่า Ruby ปฏิบัติกับ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
สำหรับคีย์สตริงเท่านั้น Ruby จะใช้สำเนาที่ถูกตรึงแทนของวัตถุเอง
2) ตัวอักษร "b", "a" และ "r" ถูกเก็บไว้เพียงครั้งเดียวสำหรับเหตุการณ์ทั้งหมด:bar
ในโปรแกรม ก่อน Ruby 2.2 มันเป็นความคิดที่ดีที่จะสร้างใหม่อย่างต่อเนื่องSymbols
ซึ่งไม่เคยนำกลับมาใช้ใหม่เนื่องจากจะอยู่ในตารางการค้นหา Symbol ทั่วโลกตลอดไป Ruby 2.2 จะเก็บขยะพวกเขาดังนั้นไม่ต้องกังวล
3) ที่จริงแล้วการคำนวณแฮชสำหรับ Symbol ไม่ได้ใช้เวลาใน Ruby 1.8.x เนื่องจาก ID วัตถุถูกใช้โดยตรง:
:bar.object_id == :bar.hash # => true in Ruby 1.8.7
ใน Ruby 1.9.x สิ่งนี้มีการเปลี่ยนแปลงเมื่อแฮชเปลี่ยนจากเซสชันหนึ่งเป็นอีกเซสชันหนึ่ง (รวมถึงเซสชันSymbols
):
:bar.hash # => some number that will be different next time Ruby 1.9 is ran
Re: อะไรคือข้อดีของการใช้สตริง?
(มาก) การค้นหาค่าที่เร็วขึ้นเล็กน้อยเนื่องจากการแฮ็กสัญลักษณ์นั้นเทียบเท่ากับการแปลงตัวเลขเป็นจำนวนเต็มเทียบกับการแฮชสตริง
ข้อเสีย: ใช้ช่องในตารางสัญลักษณ์ของโปรแกรมที่ไม่เคยเปิดตัว
ฉันสนใจที่จะติดตามผลเกี่ยวกับสตริงที่ถูกตรึงใน Ruby 2.x
เมื่อคุณจัดการกับสตริงจำนวนมากที่มาจากการป้อนข้อความ (ตัวอย่างเช่นฉันกำลังคิดถึง HTTP params หรือ payload ผ่าน Rack เป็นต้น) มันง่ายกว่าที่จะใช้สตริงทุกที่
เมื่อคุณจัดการกับพวกเขาหลายสิบ แต่พวกเขาไม่เคยเปลี่ยน (ถ้าพวกเขาเป็น "คำศัพท์" ของธุรกิจของคุณ) ฉันชอบที่จะคิดว่าการแช่แข็งพวกเขาสามารถสร้างความแตกต่าง ฉันยังไม่ได้ทำการวัดประสิทธิภาพ แต่ฉันเดาว่ามันจะเป็นการปิดการทำงานของสัญลักษณ์