Soru Bir sözlüğü değere göre nasıl sıralarım?


Bir veritabanındaki iki alandan okunan değerler sözlüğü var: bir dize alanı ve sayısal bir alan. Dize alanı benzersizdir, bu nedenle sözlüğün anahtarıdır.

Anahtarları sıralayabilirim ama değerlere göre nasıl sıralayabilirim?

Not: Stack Overflow sorusunu okudum Sözlüklerin listesini Python'daki sözlüğün değerlerine göre nasıl sıralarım? ve muhtemelen kodlarımın bir sözlük listesine sahip olması için değiştirebilirdim, ancak sözlüklerin bir listesine ihtiyaç duymadığımdan, daha basit bir çözüm olup olmadığını öğrenmek istedim.


2938
2018-03-05 00:49


Menşei


Sözlük veri yapısının doğal düzeni yoktur. Bunun üzerinden yineleyebilirsiniz, ancak yinelemenin belirli bir düzeni takip edeceğini garanti edecek hiçbir şey yoktur. Bu tasarım gereğidir, bu yüzden en iyi bahsiniz temsil için anohter veri yapısı kullanılarak probaly edilir. - Daishiman
"sıralanmış ()" sözlükler üzerinde çalışabilir (ve sıralı tuşların bir listesini döndürür), bu yüzden bunun farkında olduğunu düşünüyorum. Onun programını bilmeden, yanlış veri yapısını kullandığını söylemek saçma. Hızlı aramalar, zamanın% 90'ına ihtiyaç duyuyorsa, o zaman bir dict muhtemelen ne istersen. - bobpaul
Bunun bir kopyası olduğunu öne sürenler için stackoverflow.com/questions/72899/... Bu soru, bu sorunun bir kopyası olarak işaretlenmiştir. - Marcin
Mümkünse, NumPy'yi başlatın Series sözlükten ve kullanarak sırala pandas.Series.order - Dror
Sözlükleri sıralamak için üç çıktının (anahtarlar, değerler) her ikisi de açık ve özlü bir tarzda ele alınmıştır: stackoverflow.com/questions/16772071/sort-dict-by-value-python - JStrahl


Cevaplar:


Bir sözlüğü sıralamak, yalnızca sıralanan bir sözlükün temsili almak için mümkün değildir. Sözlükler doğal olarak düzensizdir, ancak listeler ve tuples gibi diğer türler değildir. Bu yüzden sıralı değerleri temsil etmek için sıralı bir veri türüne ihtiyacınız var. Bu liste, muhtemelen bir liste listesi olacak.

Örneğin,

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))

sorted_x her bir tupleda ikinci elemanın sıraladığı tuplların listesi olacaktır. dict(sorted_x) == x.

Ve değerler yerine anahtarlar sıralamak isteyenler için:

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(0))

Python3'te paketin açılmasına izin verilmiyor [1] kullanabiliriz

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_by_value = sorted(x.items(), key=lambda kv: kv[1])

3555
2018-03-05 00:59



değer şemalarına göre sıralama yapan çeşitli sözlüklerdeki zamanlamalar için: writeonly.wordpress.com/2008/08/30/... - Gregg Lind
sorted_x.reverse() size azalan bir emir verecektir (ikinci tuple elementi ile) - saidimu apale
saidimu: Zaten kullanıyoruz sorted(), içinde geçmek için çok daha verimli reverse=True argüman. - rmh
Python3'te bir lambda kullandım: sorted(d.items(), key=lambda x: x[1]). Bu python 2.x'te çalışır mı? - Keyo
OrderedDict, 2,7'de koleksiyonlara eklendi. Örnekte gösterilen sıralama: docs.python.org/library/... - monkut


Kadar basit: sorted(dict1, key=dict1.get)

Eh, aslında bir "sözlük değerlerine göre sıralama yapmak" mümkündür. Geçenlerde Code Golf'te (Stack Overflow sorusu) bunu yapmak zorundaydım Kod golfü: Kelime frekans şeması). Kısaltılmış, sorun türündeydi: bir metin verildiğinde, her bir sözcüğün ne sıklıkla karşı karşıya geldiğini ve en sık kullanılan sözcüklerin listesini, azalan sıklığa göre sıralayın.

Anahtar kelimeler olarak sözcükler ve her kelimenin değer sayısı olarak bir sözlük oluşturursanız şu şekilde basitleştirilir:

from collections import defaultdict
d = defaultdict(int)
for w in text.split():
  d[w] += 1

sonra kullanım sıklığına göre sıralanan kelimelerin bir listesini alabilirsiniz. sorted(d, key=d.get) - sıralama, sıralama tuşları olarak sözcük oluşumlarının sayısını kullanarak sözlük anahtarlarının üzerine yinelenir.

for w in sorted(d, key=d.get, reverse=True):
  print w, d[w]

İnsanların genellikle "Bir kelimeyi kolayca bir tuşa göre sıralayabiliyorum, ama nasıl bir değere göre sıralama yapabilirim" ifadesini kullandığını açıklamak için bu ayrıntılı açıklamayı yazıyorum - ve OP'nin böyle bir meseleyi ele almaya çalıştığını düşünüyorum. Ve çözüm, yukarıda gösterildiği gibi, değerlere dayanarak, tuşların bir listesini yapmaktır.


969
2017-07-05 08:01



Bu da iyi ama key=operator.itemgetter(1) verimlilik için daha ölçeklenebilir olmalı key=d.get - smci
İlk yapmanız gerekenler: varsayılan koleksiyonları kullanmak için - rjurney
@raylu Ben itemgetter kullanarak bir "çalışmıyor" davranış gözlemlemek: ----- from operator import itemgetter d = {"a":7, "b":1, "c":5, "d":3} sorted_keys = sorted(d, key=itemgetter, reverse=True) for key in sorted_keys: print "%s: %d" % (key, d[key])  ----- -> b: 1 c: 5 a: 7 d: 3 Kodları her çalıştırdığımda sonuçlar değişir: garip. (Üzgünüz, düzgün görüntülenecek kodu alamıyorum) - bli
@bli sorted_keys = sorted(d.items(), key=itemgetter(1), reverse=True) ve for key, val in sorted_keys: print "%s: %d" % (key, val) - itemgetter, çağrıldığında bir işlev oluşturur, örneğin örneğinizde olduğu gibi kullanmazsınız. Ve bir dict üzerinde düz bir yineleme tuşları olmadan değerleri kullanır - Izkata
sana anlatmak için gelecekten geldim collections.Counterolan bir most_common ilginizi çekebilecek yöntem :) - Eevee


Kullanabilirsin:

sorted(d.items(), key=lambda x: x[1])

Bu, sözlüğü, sözlük içindeki her girişin değerlerine göre en küçükten büyüğe doğru sıralar.


607
2018-02-13 16:33



+1 En temiz çözüm olmak için. Bununla birlikte, sözlük (karma tablosu, mümkün değil) sıralanır, aksine, sıralı bir listesini döndürür (key, value) Tuplelerin. - Keyo
@Keyo Python'a yeni geldim ve bir sözlük sıralamaya ihtiyacım vardı. Ve ben seni iyi anladığımdan emin olmak istiyorum: Bir sözlüğü sıralamak için lambda kullanmanın bir yolu yok değil mi? - lv10
Tercih ederim key=lambda (k, v): v Şahsen - Claudiu
@Claudiu Bunu sevdim (k, v) sözdizimi de var, ancak Python 3'te mevcut değil tuple parametresi açma kaldırıldı. - Bob Stein
@Nyxynyx Sadece ekle reverse=True sıralanmış bitin içinde (yani sorted(a.items(), key=lambda x: x[1], reverse=True)) - Mathime


Dicts sıralanamaz, ancak onlardan sıralanmış bir liste oluşturabilirsiniz.

Dict değerlerinin sıralanmış bir listesi:

sorted(d.values())

Değere göre sıralanmış (anahtar, değer) çiftlerinin listesi:

from operator import itemgetter
sorted(d.items(), key=itemgetter(1))

165
2018-03-05 01:05



+1: sıralanmış (d.values ​​()), Nas'ın sıralandığı (dict1, key = dict1.get) ve dolayısıyla daha Pythonic'den daha kolay okunur. Okunabilirlik hakkında, lütfen ayrıca düşünün namedtuple öneri. - Remi
Aynı değerdeki anahtarlar hangi sırayla yerleştirilir? Listeyi önce tuşlara, sonra da değerlere göre sıralıyorum, ancak aynı değerdeki tuşların sırası kalmıyor. - SabreWolfy
@Remi, bunlar iki farklı şey! sorted(d.values()) sıralı listesini döndürür değerler sözlükten, nerede sorted(d, key=d.get) listesinin döndürür anahtarlardeğerleri sırasına göre sıralandı! Farklı yol. İkincisine olan ihtiyacı görmüyorsanız, "gerçek hayat" örneği için yukarıdaki gönderiyi okuyun - Nas Banov


Son zamanlarda Python 2.7'de yeni OrderedDict öğelerin eklendiği sırayı hatırlayan tür.

>>> d = {"third": 3, "first": 1, "fourth": 4, "second": 2}

>>> for k, v in d.items():
...     print "%s: %s" % (k, v)
...
second: 2
fourth: 4
third: 3
first: 1

>>> d
{'second': 2, 'fourth': 4, 'third': 3, 'first': 1}

Orijinalden yeni, sıralı bir sözlük oluşturmak için, değerlere göre sıralayın:

>>> from collections import OrderedDict
>>> d_sorted_by_value = OrderedDict(sorted(d.items(), key=lambda x: x[1]))

OrderedDict normal bir dict gibi davranır:

>>> for k, v in d_sorted_by_value.items():
...     print "%s: %s" % (k, v)
...
first: 1
second: 2
third: 3
fourth: 4

>>> d_sorted_by_value
OrderedDict([('first': 1), ('second': 2), ('third': 3), ('fourth': 4)])

128
2017-07-05 02:50



Sorunun neyle ilgili olduğu bu değil - anahtarların sırasını korumakla ilgili değil, "değere göre sıralama" ile ilgili. - Nas Banov
@Nas Banov: Anahtar tarafından sıralama DEĞİLDİR. Sırayla sıralıyoruz, öğeleri oluşturuyoruz. bizim durumumuzda, değere göre sıralarız. maalesef, 3 maddelik dict maalesef seçildi, bu yüzden sipariş aynıydı, değer ve anahtar göre sıralı voth, bu yüzden örnek dict'ı genişlettim. - mykhal
sorted(d.items(), key=lambda x: x[1]) Ne olduğunu açıklayabilir misin x demek, neden olabilir x[1] lambda'ya Neden olmasın x[0]? Çok teşekkür ederim! - JZAU
@jie d.items() sözlükten anahtar / değer çiftlerinin bir listesini döndürür ve x bu tuple'nın bir elementidir. x[0] anahtar olacak ve x[1] değer olacak. Değeri sıralamak istediğimizden, geçiyoruz x[1] lambda'ya. - CadentOrange
@Boern d.items() liste benzeri bir kapsayıcıyı döndürür (key, value) Tuplelerin. [0] tuple'ın ilk elemanına erişir - anahtar - ve [1] ikinci elemana erişir - değer. - BallpointBen


GÜNCELLEME: 5 ARALIK 2015 Python 3.5 kullanarak

Kabul edilen cevabı faydalı bulmuşken, referans olarak güncellenmemesi beni şaşırttı. OrderedDict standart kütüphaneden koleksiyonları Tam olarak bu tür bir sorunu çözmek için tasarlanmış, uygulanabilir, modern bir alternatif olarak modül.

from operator import itemgetter
from collections import OrderedDict

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = OrderedDict(sorted(x.items(), key=itemgetter(1)))
# OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

Resmi OrderedDict dokümantasyon da çok benzer bir örnek sunuyor, ama sıralama fonksiyonu için bir lambda kullanıyor:

# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
# OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

75
2017-12-05 09:46





Genellikle kullanımı çok kullanışlı olabilir namedtuple. Örneğin, anahtar olarak 'isim' sözlüğü ve değerler olarak 'puan' sözlüğü vardır ve 'puan' üzerinde sıralamak istediğinizde:

import collections
Player = collections.namedtuple('Player', 'score name')
d = {'John':5, 'Alex':10, 'Richard': 7}

İlk önce en düşük puanla sıralama:

worst = sorted(Player(v,k) for (k,v) in d.items())

İlk önce en yüksek puanla sıralama:

best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)

Şimdi ismini ve skorunu elde edelim, ikinci en iyi oyuncuyu (index = 1) çok pythonically şöyle diyelim:

player = best[1]
player.name
    'Richard'
player.score
    7

64
2017-08-30 00:30



Onu bir sözlüğe nasıl dönüştürebilirim? - rowana
as_list = d_items () 'de (k, v) için as_list = [Player (v, k)] as_dict = dict (as_list içinde p için (p.name, p.score)) - Remi