有一个已经存在的函数,它以以下形式结束,其中d
是一个字典:
return d.iteritems()
我想要返回一个按照字典键排序的迭代器,而不是未排序的迭代器。该怎么做?
有一个已经存在的函数,它以以下形式结束,其中d
是一个字典:
return d.iteritems()
我想要返回一个按照字典键排序的迭代器,而不是未排序的迭代器。该怎么做?
虽然没有进行过非常广泛的测试,但在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)
>>>
d.items()
代替d.iteritems()
来返回一个迭代器。使用 sorted()
函数:
return sorted(dict.iteritems())
如果你想要一个实际的迭代器来遍历排序后的结果,由于sorted()
返回一个列表,所以可以使用:
return iter(sorted(dict.iteritems()))
字典的键是存储在哈希表中的,所以它们的“自然顺序”是伪随机的。任何其他排序都是字典使用者的概念。
sorted() 总是返回一个列表,而不是一个字典。如果你传递给它一个 dict.items()(它会产生一个元组列表),它将返回一个元组列表 [(k1,v1), (k2,v2), ...],可以像字典一样在循环中使用,但它 绝对不是一个字典!
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)]
for k,v in sorted(foo.items()):
print k, v
大致相当于:
for k in sorted(foo.keys()):
print k, foo[k]
sorted(foo)
替代 sorted(foo.keys())
会更好,因为在迭代字典时会返回其键(如果 sorted()
对可迭代对象的处理方式不需要创建中间列表 foo.keys()
的话,就具有这种优势)。 - Eric O. Lebigotk in sorted(foo.keys())
提取键,还是for k,v in sorted(foo.items())
返回字典的列表副本对。我猜想应该是sorted(foo.keys())
。 - CrandellWStimeit
,我会试一下。 - CrandellWSGreg的回答是正确的。请注意,在Python 3.0中,您将不得不执行
sorted(dict.items())
由于 iteritems
将被删除,因此需要进行修改。
现在在Python 2.7中也可以使用OrderedDict
:
>>> from collections import OrderedDict
>>> d = OrderedDict([('first', 1),
... ('second', 2),
... ('third', 3)])
>>> d.items()
[('first', 1), ('second', 2), ('third', 3)]
这里是2.7版本的新特性页面和OrderedDict API。
通常情况下,可以这样对字典进行排序:
for k in sorted(d):
print k, d[k]
针对问题中的特定情况,如果需要“drop in replacement”替代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 log N)的排序,但是在短暂的线性堆化后,它按顺序逐个返回项目,使得当您不总是需要整个列表时理论上更加高效。
sorted返回一个列表,因此当您尝试迭代它时会出现错误,但由于您无法对字典进行排序,因此您必须处理列表。
我不知道您的代码的更大上下文是什么,但您可以尝试向结果列表添加一个迭代器。 像这样吗?
return iter(sorted(dict.iteritems()))
{'a':1,'c':3,'b':2}
排序后它会变成一个列表:[('a',1),('b',2),('c',3)]
所以当你实际迭代这个列表时,你会得到一个元组(在这个例子中)由一个字符串和一个整数组成,但至少你能够迭代它。
.items()
代替iteritems()
:正如@Claudiu所说,iteritems()
在Python 3.x中不可用,但是items()
从Python 2.6开始就可用。 - Remiitems()
创建了一个列表,因此使用了内存,而iteritems()
基本上不使用内存。使用哪个主要取决于字典的大小。此外,自动的 Python 2 到 Python 3 转换工具 (2to3
) 会自动处理从iteritems()
到items()
的转换,所以不需要担心这个问题。 - Eric O. Lebigotcollections.OrderedDict
,排序一次后始终按排序顺序获取项目。 - Mark Harvistoniteritems()
不使用内存,sorted()
仍然需要将所有内容拉入内存,因此在内存方面,在这里使用items()
和iteritems()
之间没有区别。 - Richarditems()
时必须被存储两次(一次在items()
返回的列表中,一次在排序后的列表中),但使用iteritems()
只需要存储一次(仅在排序后的列表中)。 - Eric O. Lebigot