use*_*209 68 python dictionary python-2.x python-3.x ordereddict
我有这个:
d1 = OrderedDict([('a', '1'), ('b', '2')])
Run Code Online (Sandbox Code Playgroud)
如果我这样做:
d1.update({'c':'3'})
Run Code Online (Sandbox Code Playgroud)
然后我明白了:
OrderedDict([('a', '1'), ('b', '2'), ('c', '3')])
Run Code Online (Sandbox Code Playgroud)
但我想要这个:
[('c', '3'), ('a', '1'), ('b', '2')]
Run Code Online (Sandbox Code Playgroud)
没有创建新词典.
Ash*_*ary 67
在Python 2中没有内置的方法.如果你需要这个,你需要编写一个prepend()在OrderedDictO(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)
Run Code Online (Sandbox Code Playgroud)
演示:
>>> 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')])
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
演示:
>>> 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')])
Run Code Online (Sandbox Code Playgroud)
OrderedDict.move_to_end()(Python> = 3.2)Python 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')])
Run Code Online (Sandbox Code Playgroud)
如果我们需要插入一个元素并将其移到顶部,一步一步,我们可以直接使用它来创建一个prepend()包装器(这里没有介绍).
OrderedDict- 慢!!!如果您不想这样做并且性能不是问题,那么最简单的方法是创建一个新的dict:
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."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
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)]) #dict containing items to be added at the front
new_dic = OrderedDict((k, d2.get(k, d1.get(k))) for k in \
unique_everseen(chain(d2, d1)))
print new_dic
Run Code Online (Sandbox Code Playgroud)
输出:
OrderedDict([('c', 3), ('e', 5), ('a', '1'), ('b', '2')])
Run Code Online (Sandbox Code Playgroud)
Jar*_*red 14
编辑(2019-02-03)
请注意,以下答案仅适用于旧版本的Python.最近,OrderedDict已经用C重写了.此外,这确实触及了双下划线属性,这是不赞成的.
OrderedDict为了类似的目的,我只是在我的一个项目中编写了一个子类.这是要点.
O(1)与大多数这些解决方案不同,插入操作也是固定时间(它们不需要您重建数据结构).
>>> d1 = ListDict([('a', '1'), ('b', '2')])
>>> d1.insert_before('a', ('c', 3))
>>> d1
ListDict([('c', 3), ('a', '1'), ('b', '2')])
Run Code Online (Sandbox Code Playgroud)
dol*_*hin 12
你必须创建一个新的实例OrderedDict.如果您的钥匙是唯一的:
d1=OrderedDict([("a",1),("b",2)])
d2=OrderedDict([("c",3),("d",99)])
both=OrderedDict(list(d2.items()) + list(d1.items()))
print(both)
#OrderedDict([('c', 3), ('d', 99), ('a', 1), ('b', 2)])
Run Code Online (Sandbox Code Playgroud)
但如果没有,请注意,您可能需要或不需要此行为:
d1=OrderedDict([("a",1),("b",2)])
d2=OrderedDict([("c",3),("b",99)])
both=OrderedDict(list(d2.items()) + list(d1.items()))
print(both)
#OrderedDict([('c', 3), ('b', 2), ('a', 1)])
Run Code Online (Sandbox Code Playgroud)
如果您知道需要'c'键但不知道该值,则在创建dict时插入带有虚拟值的'c'.
d1 = OrderedDict([('c', None), ('a', '1'), ('b', '2')])
Run Code Online (Sandbox Code Playgroud)
并在以后更改该值.
d1['c'] = 3
Run Code Online (Sandbox Code Playgroud)
现在可以使用 move_to_end(key, last=True)
>>> d = OrderedDict.fromkeys('abcde')
>>> d.move_to_end('b')
>>> ''.join(d.keys())
'acdeb'
>>> d.move_to_end('b', last=False)
>>> ''.join(d.keys())
'bacde'
Run Code Online (Sandbox Code Playgroud)
https://docs.python.org/3/library/collections.html#collections.OrderedDict.move_to_end