Python'da, sıralı anahtar sırayla sözlükten nasıl yineleyebilirim?


211

Aşağıdakilerle biten mevcut bir işlev var, burada dsözlük:

return d.iteritems()

belirli bir sözlük için sıralanmamış bir yineleyici döndürür. Ben anahtar göre sıralanmış öğeleri üzerinden bir yineleyici dönmek istiyorum . Bunu nasıl yaparım?

Yanıtlar:


171

Bunu çok kapsamlı bir şekilde test etmedim, ancak Python 2.5.2'de çalışıyor.

>>> 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(): ...Yineleyiciler yerine yapmaya alışkınsanız, bu yine de yukarıdaki çözümle çalışır

>>> d = {"x":2, "h":15, "a":2222}
>>> for key, value in sorted(d.iteritems()):
>>>     print(key, value)
('a', 2222)
('h', 15)
('x', 2)
>>>

Python 3.x ile bir yineleyici döndürmek d.items()yerine kullanın d.iteritems().


29
.items()yerine kullanın iteritems(): @Claudiu'nun dediği gibi, iteritems Python 3.x için çalışmaz, ancak items()Python 2.6'dan edinilebilir.
Remi

40
Bu belli değil. Aslında, items()bir liste oluşturur ve bu nedenle belleği kullanır, oysa iteritems()esas olarak belleği kullanmaz. Ne kullanılacağı çoğunlukla sözlüğün büyüklüğüne bağlıdır. Ayrıca, Python 3 dönüştürme aracı otomatik Python 2 ( 2to3) otomatik dönüştürme ilgilenir iteritems()için items(), bu yüzden bu konuda endişe etmeye gerek yoktur.
Eric O Lebigot

5
@HowerHell bir collections.OrderedDictkez kullanın ve öğeleri her zaman sıralı düzende alın.
Mark Harviston

9
Ancak @EOL, iteritems()bellek kullanmasa bile , her şey için belleğe çekilmelidir sorted(), bu nedenle bellek items()ile iteritems()burada kullanım arasında bir fark yoktur .
Richard

8
@Richard: Tüm öğelerin belleğe alınması gerektiği doğru olsa da, bunlar iki kez (tarafından döndürülen listede ve sıralanan listede) ve yalnızca bir kez ( yalnızca sıralanan listede) ile depolanır . items()items()iteritems()
Eric O Lebigot

83

sorted()İşlevi kullanın :

return sorted(dict.iteritems())

Sıralanan sonuçların üzerinde gerçek bir yineleyici istiyorsanız, sorted()bir liste döndürdüğü için şunu kullanın:

return iter(sorted(dict.iteritems()))

Bu benim için başarısız: <type 'exceptions.TypeError'>: iter () 'list' türünde yineleyici olmayan döndürdü
mike 0

Bunun nedeni büyük olasılıkla değişken adı olarak "dict" kullanmanızdır. "dict" aslında sözlüklerin tür adıdır. Burada "mydict" gibi başka bir ad kullanın ve işte.
utku_karatas

1
Hala çalışmıyor. Pozitif sort (), normal listenin aksine başka bir yineleyici döndürür mü?
mike

bu istisna ne zaman ve nerede oluşur? sorunsuz bir liste üzerinden yineleme yapabilirsiniz

1
Kabul etti, hop. Dosyalarda satır atlama dışında doğrudan .next () çağırdığımı sanmıyorum. Bizim iter (sıralanmış (dict.iteritems ())) çözümü

39

Bir diktenin anahtarları bir hashtable içinde saklanır, böylece 'doğal düzen', yani psuedo-random. Başka herhangi bir düzen, söz konusu tüketicinin konseptidir.

sort () her zaman bir liste değil, bir liste döndürür. Eğer bir dict.items () (bu, bir tuples listesi üretir) iletirseniz, bir döngüde kullanılabilen tuples [[k1, v1), (k2, v2), ...] listesini döndürür. bir dikte gibi bir şekilde, ama yine de bir dikte değil !

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şağıdaki bir döngü içinde bir dikte gibi hissediyor, ama değil, k, v içine paketlenmiş tuples bir listesi:

for k,v in sorted(foo.items()):
    print k, v

Kabaca şuna eşit:

for k in sorted(foo.keys()):
    print k, foo[k]

Tamam, ama bir Karar ya da Liste istemiyorum, bir Yineleyici istiyorum. Bir Yineleyici olmaya nasıl zorlayabilirim?
mike

2
sorted(foo.keys())eşdeğer olarak daha iyidir sorted(foo), çünkü sözlükler yinelendiğinde anahtarlarını döndürürler ( foo.keys()belki de sorted()tekrarlanabilirler için nasıl uygulandığına bağlı olarak , ara listeyi oluşturmak zorunda kalmama avantajı ile).
Eric O Lebigot

Hızları ve / veya k in sorted(foo.keys()):anahtarları çeken veya for k,v in sorted(foo.items()):sözlüğün liste çiftlerinin bir kopyasını döndüren bellek için daha iyi olduğunu merak ediyorumsorted(foo.keys())
CrandellWS

1
@CrandellWS: Zaman sorusunu cevaplamanın en iyi yolu Python timeit modülünü kullanmaktır.
Peter Rowell

1
@frank - Kısa Cevap: Hayır. Bir dikte, gerçek anahtarın verilen anahtarın değerinin bir karması olduğu bir dizidir . Bazı uygulamalar oldukça tahmin edilebilir olsa da, bazıları bu sözleşmeyi bile yapabilir, ancak karma sipariş söz konusu olduğunda hiçbir şeye güvenmiyorum . Bkz Bu yayını 3.6+ davranışı üzerinde daha fazlası. Özellikle ilk cevaba dikkat edin.
Peter Rowell

31

Greg'in yanıtı doğru. Python 3.0'da şunları yapmanız gerektiğini unutmayın

sorted(dict.items())

olarak iteritemsgitmiş olacak.


Bu benim için başarısız: <type 'exceptions.TypeError'>: iter () 'list' türünde yineleyici olmayan döndürdü
mike 0

3
"Arabaları kullanmayın çünkü gelecekte hoverboard'larımız olacak"
JJ

7

Artık OrderedDictPython 2.7'de de kullanabilirsiniz :

>>> from collections import OrderedDict
>>> d = OrderedDict([('first', 1),
...                  ('second', 2),
...                  ('third', 3)])
>>> d.items()
[('first', 1), ('second', 2), ('third', 3)]

Burada 2.7 sürümü ve OrderedDict API için yeni sayfa var .


Bu anahtar, değerleri girildikleri sırayla döndürür - sıralı bir sırayla değil (alfabetik olarak).
Tony Suffolk 66

5

Genel olarak bir kişi şu şekilde sıralanabilir:

for k in sorted(d):
    print k, d[k]

Söz konusu özel durum için, d.iteritems () için "yedekte bir düşüş" olması gibi bir işlev ekleyin:

def sortdict(d, **opts):
    # **opts so any currently supported sorted() options can be passed
    for k in sorted(d, **opts):
        yield k, d[k]

ve böylece bitiş çizgisi

return dict.iteritems()

için

return sortdict(dict)

veya

return sortdict(dict, reverse = True)

5
>>> 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)

Bu yöntemin hala bir O (N log N) türü vardır, ancak kısa bir doğrusal yığınlamadan sonra, öğeleri listeye göre sıralı olarak verir ve her zaman tüm listeye ihtiyacınız olmadığında teorik olarak daha verimli hale getirir.


4

Anahtarların sırası yerine öğelerin eklenme sırasına göre sıralamak istiyorsanız, Python'un koleksiyonlarına bir göz atmanız gerekir . (Yalnızca Python 3)


3

sıralanmış bir liste döndürür, bu nedenle listeyi yinelemeye çalıştığınızda hata yaparsınız, ancak bir diksiyon sipariş edemediğiniz için bir listeyle uğraşmanız gerekir.

Kodunuzun daha büyük bağlamının ne olduğu hakkında hiçbir fikrim yok, ancak sonuç listesine bir yineleyici eklemeyi deneyebilirsiniz. belki böyle mi ?:

return iter(sorted(dict.iteritems()))

Tabii ki şimdi tuples geri alacaksınız çünkü sıralanmış sizin dikte tuples listesine dönüştürdü

ex: dict'inizin olduğunu söyleyin: {'a':1,'c':3,'b':2} sıralanmış bir listeye dönüştürür:

[('a',1),('b',2),('c',3)]

böylece listeyi gerçekten yinelediğinizde (bu örnekte) bir dize ve bir tamsayıdan oluşan bir demet alırsınız, ancak en azından listeyi yineleyebilirsiniz.


2

CPython 2.x kullandığınızı ve büyük bir sözlük alanına sahip olduğunuzu varsayarsak, sıralanmış (mydict) kullanmak yavaş olur çünkü sıralanmış, mydict tuşlarının sıralı bir listesini oluşturur.

Bu durumda, C'nin bir uygulamasını içeren sipariş edilen paketimize bakmak isteyebilirsiniz. sorteddict , C'de . Özellikle de sözlüklerin yaşamının farklı aşamalarında (yani öğe sayısı) sıralanmış anahtar listesini birden çok kez gözden geçirmek zorunda kalırsanız.

http://anthon.home.xs4all.nl/Python/ordereddict/

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.