ไม่มีวิธีการในตัวในการทำสิ่งนี้ใน Python 2 หากคุณต้องการสิ่งนี้คุณต้องเขียนprepend()
วิธีการ / ฟังก์ชั่นที่ทำงานบนOrderedDict
ภายในที่มีความซับซ้อน O (1)
สำหรับ Python 3.2 และใหม่กว่าคุณควรใช้move_to_end
เมธอด เมธอดยอมรับlast
อาร์กิวเมนต์ซึ่งระบุว่าองค์ประกอบจะถูกย้ายไปที่ด้านล่าง ( last=True
) หรือด้านบน ( last=False
) ของOrderedDict
.
สุดท้ายหากคุณต้องการวิธีแก้ปัญหาที่รวดเร็วสกปรกและช้าคุณสามารถสร้างใหม่OrderedDict
ตั้งแต่ต้น
รายละเอียดสำหรับสี่โซลูชันที่แตกต่างกัน:
ขยายOrderedDict
และเพิ่มวิธีการอินสแตนซ์ใหม่
from collections import OrderedDict
class MyOrderedDict(OrderedDict):
def prepend(self, key, value, dict_setitem=dict.__setitem__):
root = self._OrderedDict__root
first = root[1]
if key in self:
link = self._OrderedDict__map[key]
link_prev, link_next, _ = link
link_prev[1] = link_next
link_next[0] = link_prev
link[0] = root
link[1] = first
root[1] = first[0] = link
else:
root[1] = first[0] = self._OrderedDict__map[key] = [root, first, key]
dict_setitem(self, key, value)
การสาธิต:
>>> d = MyOrderedDict([('a', '1'), ('b', '2')])
>>> d
MyOrderedDict([('a', '1'), ('b', '2')])
>>> d.prepend('c', 100)
>>> d
MyOrderedDict([('c', 100), ('a', '1'), ('b', '2')])
>>> d.prepend('a', d['a'])
>>> d
MyOrderedDict([('a', '1'), ('c', 100), ('b', '2')])
>>> d.prepend('d', 200)
>>> d
MyOrderedDict([('d', 200), ('a', '1'), ('c', 100), ('b', '2')])
ฟังก์ชันสแตนด์อโลนที่จัดการกับOrderedDict
วัตถุ
ฟังก์ชันนี้ทำสิ่งเดียวกันโดยยอมรับวัตถุ dict คีย์และค่า ฉันชอบชั้นเรียนเป็นการส่วนตัว:
from collections import OrderedDict
def ordered_dict_prepend(dct, key, value, dict_setitem=dict.__setitem__):
root = dct._OrderedDict__root
first = root[1]
if key in dct:
link = dct._OrderedDict__map[key]
link_prev, link_next, _ = link
link_prev[1] = link_next
link_next[0] = link_prev
link[0] = root
link[1] = first
root[1] = first[0] = link
else:
root[1] = first[0] = dct._OrderedDict__map[key] = [root, first, key]
dict_setitem(dct, key, value)
การสาธิต:
>>> d = OrderedDict([('a', '1'), ('b', '2')])
>>> ordered_dict_prepend(d, 'c', 100)
>>> d
OrderedDict([('c', 100), ('a', '1'), ('b', '2')])
>>> ordered_dict_prepend(d, 'a', d['a'])
>>> d
OrderedDict([('a', '1'), ('c', 100), ('b', '2')])
>>> ordered_dict_prepend(d, 'd', 500)
>>> d
OrderedDict([('d', 500), ('a', '1'), ('c', 100), ('b', '2')])
ใช้OrderedDict.move_to_end()
(Python> = 3.2)
งูหลาม 3.2 แนะนำOrderedDict.move_to_end()
วิธี ใช้มันเราสามารถย้ายคีย์ที่มีอยู่ไปยังจุดสิ้นสุดของพจนานุกรมในเวลา O (1)
>>> d1 = OrderedDict([('a', '1'), ('b', '2')])
>>> d1.update({'c':'3'})
>>> d1.move_to_end('c', last=False)
>>> d1
OrderedDict([('c', '3'), ('a', '1'), ('b', '2')])
หากเราต้องการแทรกองค์ประกอบและย้ายไปด้านบนทั้งหมดในขั้นตอนเดียวเราสามารถใช้มันเพื่อสร้างprepend()
กระดาษห่อหุ้มได้โดยตรง(ไม่ได้นำเสนอที่นี่)
สร้างใหม่OrderedDict
- ช้า !!!
หากคุณไม่ต้องการทำเช่นนั้นและประสิทธิภาพไม่ใช่ปัญหาวิธีที่ง่ายที่สุดคือสร้างคำสั่งใหม่:
from itertools import chain, ifilterfalse
from collections import OrderedDict
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
seen = set()
seen_add = seen.add
if key is None:
for element in ifilterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
d1 = OrderedDict([('a', '1'), ('b', '2'),('c', 4)])
d2 = OrderedDict([('c', 3), ('e', 5)])
new_dic = OrderedDict((k, d2.get(k, d1.get(k))) for k in \
unique_everseen(chain(d2, d1)))
print new_dic
เอาต์พุต:
OrderedDict([('c', 3), ('e', 5), ('a', '1'), ('b', '2')])