Python 2'de bunu yapmak için yerleşik bir yöntem yoktur. Buna ihtiyacınız varsa , O (1) karmaşıklığı ile dahili prepend()
üzerinde çalışan bir yöntem / işlev yazmanız gerekir OrderedDict
.
Python 3.2 ve daha yeni sürümler, sen gerektiğini kullanmak move_to_end
yöntemini. Yöntem last
, öğenin .txt dosyasının altına ( last=True
) veya üstüne ( last=False
) taşınacağını belirten bir bağımsız değişken kabul eder OrderedDict
.
Son olarak, hızlı, kirli ve yavaş bir çözüm istiyorsanız, OrderedDict
sıfırdan yeni bir çözüm oluşturabilirsiniz .
Dört farklı çözümün ayrıntıları:
OrderedDict
Yeni bir örnek yöntemini genişletin ve ekleyin
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)
Demo:
>>> 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
Nesneleri manipüle eden bağımsız işlev
Bu işlev, dikte nesnesini, anahtarı ve değeri kabul ederek aynı şeyi yapar. Ben şahsen sınıfı tercih ediyorum:
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)
Demo:
>>> 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) kullanın
Python 3.2 tanıtıldıOrderedDict.move_to_end()
yöntemi. Bunu kullanarak, mevcut bir anahtarı O (1) zamanında sözlüğün herhangi bir ucuna taşıyabiliriz.
>>> 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')])
Bir öğeyi eklememiz ve en üste taşımamız gerekirse, hepsi tek adımda, onu doğrudan bir prepend()
sarmalayıcı oluşturmak için kullanabiliriz (burada gösterilmemiştir).
Yeni bir OrderedDict
- yavaş oluşturun !!!
Bunu yapmak istemiyorsanız ve performans bir sorun değilse, en kolay yol yeni bir dikte oluşturmaktır:
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
çıktı:
OrderedDict([('c', 3), ('e', 5), ('a', '1'), ('b', '2')])