Respostas:
Não testou isso muito extensivamente, mas funciona no 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)
>>>
Se você está acostumado a fazer, em for key, value in d.iteritems(): ...
vez de iteradores, isso ainda funcionará com a solução acima
>>> d = {"x":2, "h":15, "a":2222}
>>> for key, value in sorted(d.iteritems()):
>>> print(key, value)
('a', 2222)
('h', 15)
('x', 2)
>>>
Com o Python 3.x, use em d.items()
vez de d.iteritems()
retornar um iterador.
items()
cria uma lista e, portanto, usa memória, enquanto que iteritems()
essencialmente não usa memória. O que usar depende principalmente do tamanho do dicionário. Além disso, a ferramenta de conversão automática Python 2 para Python 3 ( 2to3
) cuida automaticamente da conversão de iteritems()
para items()
, então não há necessidade de se preocupar com isso.
collections.OrderedDict
então você classifica uma vez e obtém os itens sempre na ordem de classificação.
iteritems()
que não use memória, tudo deve ser puxado para a memória sorted()
, para que não haja diferença entre o uso da memória items()
e iteritems()
aqui.
items()
(na lista retornada por items()
e na lista classificada) e apenas uma vez com iteritems()
(apenas na lista classificada).
Use a sorted()
função:
return sorted(dict.iteritems())
Se você deseja um iterador real sobre os resultados classificados, pois sorted()
retorna uma lista, use:
return iter(sorted(dict.iteritems()))
As chaves de um ditado são armazenadas em uma hashtable, de modo que essa é sua 'ordem natural', isto é, psuedo-random. Qualquer outra ordem é um conceito do consumidor do ditado.
classificado () sempre retorna uma lista, não um ditado. Se você passar um dict.items () (que produz uma lista de tuplas), ele retornará uma lista de tuplas [(k1, v1), (k2, v2), ...] que podem ser usadas em um loop de uma maneira muito parecida com um ditado, mas de modo algum é um ditado !
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)]
A seguir, parece um ditado em um loop, mas não é, é uma lista de tuplas sendo descompactadas em k, v:
for k,v in sorted(foo.items()):
print k, v
Aproximadamente equivalente a:
for k in sorted(foo.keys()):
print k, foo[k]
sorted(foo.keys())
é melhor que o equivalente sorted(foo)
, já que os dicionários retornam suas chaves quando iterados (com a vantagem de não serem forçados a criar a foo.keys()
lista intermediária, talvez - dependendo de como sorted()
é implementado para iterables).
k in sorted(foo.keys()):
que puxa as chaves ou for k,v in sorted(foo.items()):
que retorna uma cópia da lista de pares do dicionário eu achosorted(foo.keys())
Agora você também pode usar o OrderedDict
Python 2.7:
>>> from collections import OrderedDict
>>> d = OrderedDict([('first', 1),
... ('second', 2),
... ('third', 3)])
>>> d.items()
[('first', 1), ('second', 2), ('third', 3)]
Aqui você tem a nova que é página para 2,7 versão ea API OrderedDict .
Em geral, pode-se classificar um ditado assim:
for k in sorted(d):
print k, d[k]
Para o caso específico da pergunta, com uma "queda na substituição" de d.iteritems (), adicione uma função como:
def sortdict(d, **opts):
# **opts so any currently supported sorted() options can be passed
for k in sorted(d, **opts):
yield k, d[k]
e assim a linha final muda de
return dict.iteritems()
para
return sortdict(dict)
ou
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)
Esse método ainda possui uma classificação O (N log N); no entanto, após um pequeno heapify linear, ele produz os itens na ordem de classificação conforme o andamento, tornando-o teoricamente mais eficiente quando você nem sempre precisa da lista inteira.
Se você deseja classificar pela ordem em que os itens foram inseridos, em vez da ordem das chaves, consulte as coleções do Python.OrderedDict . (Somente Python 3)
classificado retorna uma lista, daí o seu erro ao tentar iterá-lo, mas como você não pode ordenar um ditado, precisará lidar com uma lista.
Não faço ideia do contexto maior do seu código, mas você pode tentar adicionar um iterador à lista resultante. assim talvez ?:
return iter(sorted(dict.iteritems()))
é claro que você receberá de volta as tuplas agora porque classificadas transformou seu ditado em uma lista de tuplas
ex: diga que seu ditado era:
{'a':1,'c':3,'b':2}
classificado transforma-o em uma lista:
[('a',1),('b',2),('c',3)]
portanto, quando você realmente itera sobre a lista, recebe (neste exemplo) uma tupla composta por uma string e um número inteiro, mas pelo menos você poderá iterar sobre ela.
Supondo que você esteja usando o CPython 2.xe possua um grande dicionário mydict, o uso de ordenado (mydict) será lento, porque ordenado cria uma lista ordenada das chaves do mydict.
Nesse caso, você pode querer olhar para o meu pacote ordersdict, que inclui uma implementação C de sorteddict
em C. Especialmente se você precisar a lista classificada de chaves várias vezes em diferentes estágios (ou seja, número de elementos) da vida útil dos dicionários.
.items()
vez deiteritems()
: como o @Claudiu disse, os iteritems não funcionam no Python 3.x, masitems()
estão disponíveis no Python 2.6.