วิธีที่ถูกต้องในการเริ่มต้น OrderDict โดยใช้ตัวสร้างเพื่อที่จะรักษาลำดับของข้อมูลเริ่มต้น?


124

อะไรคือวิธีที่ถูกต้องในการเริ่มต้นพจนานุกรมแบบเรียงลำดับ (OD) เพื่อที่จะรักษาลำดับของข้อมูลเริ่มต้น

from collections import OrderedDict

# Obviously wrong because regular dict loses order
d = OrderedDict({'b':2, 'a':1}) 

# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b',2), ('a', 1)])

# What about using a list comprehension, will 'd' preserve the order of 'l'
l = ['b', 'a', 'c', 'aa']
d = OrderedDict([(i,i) for i in l])

คำถาม:

  • จะOrderedDictรักษาลำดับของรายการทูเปิลหรือทูเพิลของทูเพิลหรือทูเพิลของลิสต์หรือลิสต์ลิสต์อื่น ๆ ที่ส่งผ่านในช่วงเวลาของการเริ่มต้น (ตัวอย่างที่ 2 และ 3 ด้านบน) หรือไม่

  • เราจะตรวจสอบได้อย่างไรว่าOrderedDictรักษาคำสั่งซื้อจริงหรือไม่? เนื่องจาก a dictมีคำสั่งที่ไม่สามารถคาดเดาได้จะเกิดอะไรขึ้นถ้าเวกเตอร์ทดสอบของฉันโชคดีมีลำดับเริ่มต้นเหมือนกับลำดับที่คาดเดาไม่ได้ของ Dict? ตัวอย่างเช่นถ้าแทนที่d = OrderedDict({'b':2, 'a':1})ฉันจะเขียนd = OrderedDict({'a':1, 'b':2})ฉันสามารถสรุปได้อย่างผิด ๆ ว่าคำสั่งนั้นถูกเก็บรักษาไว้ ในกรณีนี้ฉันพบว่า a dictเรียงลำดับตามตัวอักษร แต่นั่นอาจไม่จริงเสมอไป วิธีใดเป็นวิธีที่เชื่อถือได้ในการใช้ตัวอย่างเพื่อตรวจสอบว่าโครงสร้างข้อมูลรักษาคำสั่งซื้อหรือไม่โดยไม่ต้องพยายามทดสอบเวกเตอร์ซ้ำ ๆ จนกว่าจะแตก

ป.ล. ฉันจะทิ้งสิ่งนี้ไว้ที่นี่เพื่อใช้อ้างอิง : "ตัวสร้าง OrderDict และวิธีการ update () ทั้งสองยอมรับอาร์กิวเมนต์คำหลัก แต่คำสั่งของพวกเขาหายไปเนื่องจากฟังก์ชันการเรียกใช้ความหมายของ Python อาร์กิวเมนต์คำหลัก pass-in โดยใช้พจนานุกรมที่ไม่มีการเรียงลำดับปกติ"

PPS: หวังว่าในอนาคต OrderDict จะรักษาลำดับของ kwargs ไว้ด้วย (ตัวอย่างที่ 1): http://bugs.python.org/issue16991


10
เป็นเรื่องน่าขันที่การเริ่มต้นคำสั่ง OrderDict ด้วยคำสั่ง (ไม่ว่างเปล่า) เป็นสิ่งที่ไม่ถูกต้อง ... เนื้อหาที่ควรส่งผลให้เกิดคำเตือนเนื่องจากอาจละเมิดเจตนาของผู้ใช้
smci

3
หลังจาก python3.6 OrderDict(b=2, a=1)ยังเป็นวิธีที่เหมาะสม ดูPEP 468
IvanaGyro

คำตอบ:


90

OrderDict จะรักษาคำสั่งซื้อใด ๆ ที่สามารถเข้าถึงได้ วิธีเดียวที่จะส่งข้อมูลที่เรียงลำดับไปยังข้อมูลเพื่อเริ่มต้นคือการส่งผ่านรายการคู่คีย์ - ค่า (หรือโดยทั่วไปสามารถทำซ้ำได้) ดังในสองตัวอย่างสุดท้ายของคุณ ตามที่เอกสารที่คุณเชื่อมโยงไปกล่าวว่า OrderDict ไม่มีสิทธิ์เข้าถึงคำสั่งใด ๆ เมื่อคุณส่งผ่านอาร์กิวเมนต์คำหลักหรืออาร์กิวเมนต์ dict เนื่องจากคำสั่งใด ๆ จะถูกลบออกก่อนที่ตัวสร้าง OrderDict จะเห็น

โปรดทราบว่าการใช้ความเข้าใจรายการในตัวอย่างสุดท้ายของคุณจะไม่เปลี่ยนแปลงอะไรเลย ไม่มีความแตกต่างระหว่างและOrderedDict([(i,i) for i in l]) OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')])ความเข้าใจของรายการจะได้รับการประเมินและสร้างรายการและจะถูกส่งผ่านไป OrderDict ไม่รู้อะไรเลยเกี่ยวกับวิธีการสร้าง


74
# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b', 2), ('a', 1)])

ใช่ว่าจะได้ผล ตามความหมายรายการจะเรียงลำดับตามวิธีที่แสดงเสมอ สิ่งนี้ใช้เพื่อความเข้าใจในรายการเช่นกันรายการที่สร้างขึ้นก็เป็นไปในลักษณะเดียวกับข้อมูลที่ให้มา (เช่นแหล่งที่มาจากรายการจะถูกกำหนดโดยมีที่มาจากsetหรือdictไม่มากนัก)

เราจะตรวจสอบได้อย่างไรว่าOrderedDictรักษาคำสั่งซื้อจริงหรือไม่ เนื่องจากคำสั่งมีคำสั่งที่ไม่สามารถคาดเดาได้จะเกิดอะไรขึ้นถ้าเวกเตอร์ทดสอบของฉันโชคดีมีลำดับเริ่มต้นเหมือนกับลำดับที่คาดเดาไม่ได้ของคำสั่ง ตัวอย่างเช่นถ้าแทนที่d = OrderedDict({'b':2, 'a':1})ฉันจะเขียนd = OrderedDict({'a':1, 'b':2})ฉันสามารถสรุปได้อย่างผิด ๆ ว่าคำสั่งนั้นถูกเก็บรักษาไว้ ในกรณีนี้ฉันพบว่า a dictเรียงลำดับตามตัวอักษร แต่นั่นอาจไม่จริงเสมอไป นั่นคือวิธีที่เชื่อถือได้ในการใช้ตัวอย่างตัวนับเพื่อตรวจสอบว่าโครงสร้างข้อมูลรักษาคำสั่งซื้อหรือไม่พยายามทดสอบเวกเตอร์ซ้ำ ๆ จนกว่าจะแตก

คุณเก็บรายชื่อแหล่งที่มาของ 2-tuple ไว้เพื่อใช้อ้างอิงและใช้เป็นข้อมูลทดสอบสำหรับกรณีทดสอบของคุณเมื่อคุณทำการทดสอบหน่วย ทำซ้ำผ่านพวกเขาและตรวจสอบให้แน่ใจว่าคำสั่งซื้อได้รับการดูแล


เกี่ยวกับการตรวจสอบคำสั่งซื้อ: ฉันจะแน่ใจได้อย่างไรว่า 2-tuple ของฉันจะทำลายลำดับของ dict หากไม่สามารถคาดเดาได้ นี่เป็นคำถามทั่วไปเกี่ยวกับโครงสร้างข้อมูลบางทีฉันควรแยกออกจากคำถามนี้
คลิก

1
คุณไม่สามารถทำลายสิ่งที่ไม่ได้กำหนดโดยธรรมชาติได้อย่างแน่นอน
metatoaster

1
แล้วแนวทางที่ถูกต้องในการทดสอบสิ่งเหล่านี้คืออะไร? คุณแค่พยายามไปเรื่อย ๆ ? คำสั่งนั้นไม่สามารถคาดเดาได้สำหรับโปรแกรมเมอร์ แต่เนื่องจากเป็นแผนที่แฮชจึงเป็นไปตามอัลกอริทึม 'บางอย่าง' และการทดสอบที่ถูกต้องควรพยายามตอบโต้หรือไม่
คลิก

2
ดู__hash__. โดยเฉพาะเกี่ยวกับstrประเภท
metatoaster

ตามความหมายรายการจะเรียงลำดับตามวิธีที่แสดงเสมอ นี่เป็นคำชี้แจงที่สำคัญสำหรับฉัน ฉันตัดสินใจที่จะใช้รายการ 2 tuples สำหรับพื้นฐานของฉันOrderedDictเพื่อที่ฉันจะได้ไม่มีค่าใช้จ่ายในการแปลงรายการเป็นOrderedDictไฟล์. ฉันแค่วนซ้ำองค์ประกอบต่างๆเช่นรายการแทนที่จะเป็นพจนานุกรม
Bobort
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.