มีฟังก์ชันที่มีอยู่ซึ่งลงท้ายด้วยต่อไปนี้โดยที่d
เป็นพจนานุกรม:
return d.iteritems()
ที่ส่งคืนตัววนซ้ำที่ไม่เรียงลำดับสำหรับพจนานุกรมที่กำหนด ผมอยากจะกลับ iterator ที่ต้องผ่านรายการที่เรียงโดยคีย์ ฉันจะทำอย่างไร
มีฟังก์ชันที่มีอยู่ซึ่งลงท้ายด้วยต่อไปนี้โดยที่d
เป็นพจนานุกรม:
return d.iteritems()
ที่ส่งคืนตัววนซ้ำที่ไม่เรียงลำดับสำหรับพจนานุกรมที่กำหนด ผมอยากจะกลับ iterator ที่ต้องผ่านรายการที่เรียงโดยคีย์ ฉันจะทำอย่างไร
คำตอบ:
ยังไม่ได้ทดสอบสิ่งนี้อย่างกว้างขวาง แต่ทำงานใน Python 2.5.2
>>> d = {"x":2, "h":15, "a":2222}
>>> it = iter(sorted(d.iteritems()))
>>> it.next()
('a', 2222)
>>> it.next()
('h', 15)
>>> it.next()
('x', 2)
>>>
หากคุณคุ้นเคยกับการทำfor key, value in d.iteritems(): ...
ซ้ำแทนที่จะใช้ตัววนซ้ำสิ่งนี้จะยังคงใช้ได้กับวิธีแก้ไขปัญหาข้างต้น
>>> d = {"x":2, "h":15, "a":2222}
>>> for key, value in sorted(d.iteritems()):
>>> print(key, value)
('a', 2222)
('h', 15)
('x', 2)
>>>
ด้วย Python 3.x ให้ใช้d.items()
แทนd.iteritems()
การส่งคืนตัววนซ้ำ
items()
สร้างรายการและดังนั้นจึงใช้หน่วยความจำในขณะที่iteritems()
เป็นหลักไม่ได้ใช้หน่วยความจำ สิ่งที่ใช้ส่วนใหญ่ขึ้นอยู่กับขนาดของพจนานุกรม นอกจากนี้หลามอัตโนมัติ 2 ถึง 3 หลามเครื่องมือการแปลง ( 2to3
) จะดูแลการแปลงจากiteritems()
ไปitems()
จึงมีความจำเป็นที่จะต้องกังวลเกี่ยวกับเรื่องนี้
collections.OrderedDict
แล้วคุณเรียงครั้งเดียวและรับรายการในการเรียงลำดับเสมอ
iteritems()
จะไม่ได้ใช้หน่วยความจำทุกอย่างจะต้องถูกดึงเข้าไปในหน่วยความจำsorted()
ดังนั้นจึงไม่มีความแตกต่างระหว่างการใช้งานitems()
และiteritems()
ที่นี่หน่วยความจำที่ชาญฉลาด
items()
(ในรายการกลับมาitems()
และในรายการเรียง) และเพียงครั้งเดียวกับiteritems()
(ในรายการเรียงเท่านั้น)
ใช้sorted()
ฟังก์ชั่น:
return sorted(dict.iteritems())
หากคุณต้องการตัววนซ้ำจริงเหนือผลลัพธ์ที่เรียงลำดับเนื่องจากsorted()
ส่งคืนรายการให้ใช้:
return iter(sorted(dict.iteritems()))
คีย์ของ dict ถูกเก็บไว้ใน hashtable เพื่อให้เป็น 'ลำดับธรรมชาติ' ของพวกเขานั่นคือ psuedo-random การสั่งซื้ออื่นใด ๆ เป็นแนวคิดของผู้บริโภคของ dict
เรียง () จะส่งคืนรายการเสมอไม่ใช่ dict ถ้าคุณส่งมันเป็น dict.items () (ซึ่งสร้างรายการของ tuples) มันจะส่งคืนรายการของ tuples [(k1, v1), (k2, v2), ... ] ซึ่งสามารถใช้เป็นวง ในทางที่มากเหมือน dict แต่มันไม่ได้อยู่ใน dict !
foo = {
'a': 1,
'b': 2,
'c': 3,
}
print foo
>>> {'a': 1, 'c': 3, 'b': 2}
print foo.items()
>>> [('a', 1), ('c', 3), ('b', 2)]
print sorted(foo.items())
>>> [('a', 1), ('b', 2), ('c', 3)]
ต่อไปนี้ให้ความรู้สึกเหมือน dict ในวง แต่ไม่ใช่มันเป็นรายการของ tuples ที่ถูกแตกออกเป็น k, v:
for k,v in sorted(foo.items()):
print k, v
เทียบเท่ากับ:
for k in sorted(foo.keys()):
print k, foo[k]
sorted(foo.keys())
ดีกว่าเทียบเท่าsorted(foo)
เนื่องจากพจนานุกรมส่งคืนคีย์ของพวกเขาเมื่อมีการวนซ้ำ (ด้วยความได้เปรียบของการไม่ถูกบังคับให้สร้างfoo.keys()
รายการกลางอาจขึ้นอยู่กับวิธีsorted()
การนำไปใช้กับ iterables)
k in sorted(foo.keys()):
ที่ดึงกุญแจหรือfor k,v in sorted(foo.items()):
คืนสำเนาของรายการพจนานุกรมที่ฉันเดาsorted(foo.keys())
คุณสามารถใช้งานOrderedDict
Python 2.7 ได้แล้วในตอนนี้:
>>> from collections import OrderedDict
>>> d = OrderedDict([('first', 1),
... ('second', 2),
... ('third', 3)])
>>> d.items()
[('first', 1), ('second', 2), ('third', 3)]
ที่นี่คุณมีอะไรใหม่หน้า 2.7 รุ่นและOrderedDict API
โดยทั่วไปแล้วคนหนึ่งอาจเรียงลำดับ dict ดังนี้:
for k in sorted(d):
print k, d[k]
สำหรับกรณีเฉพาะในคำถามโดยมี "การแทนที่แบบแทนที่" สำหรับ d.iteritems () ให้เพิ่มฟังก์ชันดังนี้:
def sortdict(d, **opts):
# **opts so any currently supported sorted() options can be passed
for k in sorted(d, **opts):
yield k, d[k]
และดังนั้นบรรทัดสุดท้ายจึงเปลี่ยนจาก
return dict.iteritems()
ถึง
return sortdict(dict)
หรือ
return sortdict(dict, reverse = True)
>>> import heapq
>>> d = {"c": 2, "b": 9, "a": 4, "d": 8}
>>> def iter_sorted(d):
keys = list(d)
heapq.heapify(keys) # Transforms to heap in O(N) time
while keys:
k = heapq.heappop(keys) # takes O(log n) time
yield (k, d[k])
>>> i = iter_sorted(d)
>>> for x in i:
print x
('a', 4)
('b', 9)
('c', 2)
('d', 8)
วิธีนี้ยังคงมีการเรียงลำดับ O (N บันทึก N) อย่างไรก็ตามหลังจาก heapify เชิงเส้นสั้น ๆ มันให้ผลผลิตรายการในการเรียงลำดับตามที่ไปทำให้ทฤษฎีมีประสิทธิภาพมากขึ้นเมื่อคุณไม่ต้องการรายการทั้งหมด
เรียงลำดับส่งกลับรายการดังนั้นข้อผิดพลาดของคุณเมื่อคุณพยายามที่จะทำซ้ำมากกว่า แต่เพราะคุณไม่สามารถสั่ง dict คุณจะต้องจัดการกับรายการ
ฉันไม่รู้ว่าบริบทของโค้ดของคุณใหญ่กว่าอะไร แต่คุณสามารถลองเพิ่มตัววนซ้ำไปยังรายการผลลัพธ์ได้ อาจจะเป็นแบบนี้:
return iter(sorted(dict.iteritems()))
แน่นอนคุณจะได้รับผลตอบแทน tuples ในขณะนี้เพราะเรียงลำดับหัน dict ของคุณลงในรายการของสิ่งอันดับ
ตัวอย่าง: บอกว่า dict ของคุณคือ:
{'a':1,'c':3,'b':2}
เรียงลำดับเปลี่ยนเป็นรายการ:
[('a',1),('b',2),('c',3)]
ดังนั้นเมื่อคุณวนซ้ำในรายการคุณจะได้รับกลับมา (ในตัวอย่างนี้) tuple ที่ประกอบด้วยสตริงและจำนวนเต็ม แต่อย่างน้อยคุณจะสามารถทำซ้ำได้
สมมติว่าคุณกำลังใช้ CPython 2.x และมีพจนานุกรม mydict ขนาดใหญ่จากนั้นการใช้ sort (mydict) จะช้าลงเนื่องจากการเรียงลำดับจะสร้างรายการเรียงลำดับของคีย์ของ mydict
ในกรณีนี้คุณอาจต้องการดูแพคเกจ ordereddict ของฉันซึ่งรวมถึงการนำ C ไปใช้sorteddict
ใน C โดยเฉพาะอย่างยิ่งถ้าคุณต้องข้ามรายการเรียงลำดับของคีย์หลายครั้งในระยะต่าง ๆ (เช่นจำนวนองค์ประกอบ) ของอายุการใช้งานพจนานุกรม
.items()
แทนiteritems()
: ตามที่ @Claudiu กล่าวว่า iteritems ไม่สามารถใช้กับ Python 3.x ได้ แต่items()
มีให้จาก Python 2.6