Không có phương thức tích hợp nào để thực hiện việc này trong Python 2. Nếu bạn cần điều này, bạn cần viết một prepend()
phương thức / hàm hoạt động trên OrderedDict
nội bộ với độ phức tạp O (1).
Đối với Python 3.2 trở lên, bạn nên sử dụng move_to_end
phương pháp này. Phương thức chấp nhận một last
đối số cho biết liệu phần tử sẽ được chuyển đến dưới cùng ( last=True
) hay đầu ( last=False
) của OrderedDict
.
Cuối cùng, nếu bạn muốn một giải pháp nhanh, bẩn và chậm , bạn có thể tạo một giải pháp mới OrderedDict
từ đầu.
Chi tiết về bốn giải pháp khác nhau:
Mở rộng OrderedDict
và thêm một phương thức phiên bản mới
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)
Bản giới thiệu:
>>> 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')])
Chức năng độc lập điều khiển OrderedDict
các đối tượng
Hàm này thực hiện điều tương tự bằng cách chấp nhận đối tượng dict, khóa và giá trị. Cá nhân tôi thích lớp học hơn:
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)
Bản giới thiệu:
>>> 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')])
Sử dụng OrderedDict.move_to_end()
(Python> = 3.2)
Python 3.2 giới thiệu các OrderedDict.move_to_end()
phương pháp. Sử dụng nó, chúng ta có thể di chuyển một khóa hiện có đến một trong hai đầu của từ điển trong thời gian 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')])
Nếu chúng ta cần chèn một phần tử và di chuyển nó lên trên cùng, tất cả chỉ trong một bước, chúng ta có thể trực tiếp sử dụng nó để tạo một prepend()
trình bao bọc (không được trình bày ở đây).
Tạo mới OrderedDict
- chậm !!!
Nếu bạn không muốn làm điều đó và hiệu suất không phải là vấn đề thì cách dễ nhất là tạo một mệnh đề mới:
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
đầu ra:
OrderedDict([('c', 3), ('e', 5), ('a', '1'), ('b', '2')])