Pertanyaan Bagaimana cara mengurutkan kamus berdasarkan nilai?


Saya memiliki kamus nilai yang dibaca dari dua bidang dalam database: bidang string dan bidang numerik. Bidang string unik, jadi itulah kunci kamus.

Saya bisa mengurutkan kunci, tapi bagaimana saya bisa mengurutkan berdasarkan nilai-nilai?

Catatan: Saya telah membaca pertanyaan Stack Overflow Bagaimana cara mengurutkan daftar kamus berdasarkan nilai-nilai kamus dengan Python? dan mungkin bisa mengubah kode saya untuk memiliki daftar kamus, tetapi karena saya tidak benar-benar memerlukan daftar kamus, saya ingin tahu apakah ada solusi yang lebih sederhana.


2932
2018-03-05 00:49


asal


Jawaban:


Tidak mungkin mengurutkan kamus, hanya untuk mendapatkan representasi kamus yang disortir. Kamus pada dasarnya tidak memiliki perintah, tetapi jenis lain, seperti daftar dan tupel, tidak. Jadi Anda memerlukan tipe data yang diurutkan untuk mewakili nilai yang diurutkan, yang akan menjadi daftar — mungkin daftar tupel.

Contohnya,

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

sorted_x akan menjadi daftar tupel yang diurutkan berdasarkan elemen kedua di setiap tupel. dict(sorted_x) == x.

Dan bagi mereka yang ingin memilah kunci bukannya nilai:

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

Di Python3 karena membongkar tidak diperbolehkan [1] kita bisa gunakan

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

3550
2018-03-05 00:59



Sesederhana seperti: sorted(dict1, key=dict1.get)

Yah, sebenarnya mungkin untuk melakukan "urutkan berdasarkan nilai kamus". Baru-baru ini saya harus melakukan itu dalam Kode Golf (pertanyaan Stack Overflow Golf kode: Bagan frekuensi kata). Ringkasnya, masalahnya adalah jenisnya: diberi teks, menghitung seberapa sering setiap kata ditemui dan menampilkan daftar kata teratas, diurutkan berdasarkan frekuensi yang menurun.

Jika Anda membuat kamus dengan kata-kata sebagai kunci dan jumlah kemunculan setiap kata sebagai nilai, disederhanakan di sini sebagai:

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

maka Anda bisa mendapatkan daftar kata-kata, diperintahkan oleh frekuensi penggunaan dengan sorted(d, key=d.get) - sort iterates di atas tombol kamus, menggunakan jumlah kejadian kata sebagai semacam kunci.

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

Saya menulis penjelasan terperinci ini untuk mengilustrasikan apa yang sering orang maksud dengan "Saya dapat dengan mudah mengurutkan kamus berdasarkan kunci, tetapi bagaimana saya mengurutkan berdasarkan nilai" - dan saya pikir OP sedang mencoba untuk mengatasi masalah seperti itu. Dan solusinya adalah melakukan semacam daftar kunci, berdasarkan nilai-nilai, seperti yang ditunjukkan di atas.


967
2017-07-05 08:01



Anda bisa menggunakan:

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

Ini akan mengurutkan kamus berdasarkan nilai setiap entri dalam kamus dari terkecil hingga terbesar.


601
2018-02-13 16:33



Dict tidak dapat diurutkan, tetapi Anda dapat membuat daftar yang diurutkan dari mereka.

Daftar nilai dict yang diurutkan:

sorted(d.values())

Daftar pasangan (kunci, nilai), diurutkan berdasarkan nilai:

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

165
2018-03-05 01:05



Dalam Python terbaru 2.7, kita memiliki yang baru OrderedDict jenis, yang mengingat urutan di mana barang-barang itu ditambahkan.

>>> 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}

Untuk membuat kamus pesanan baru dari aslinya, sortir berdasarkan nilai:

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

The OrderedDict berperilaku seperti perintah normal:

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



PERBARUI: 5 DESEMBER 2015 menggunakan Python 3.5

Sementara saya menemukan jawaban yang diterima berguna, saya juga terkejut bahwa itu belum diperbarui untuk referensi OrderedDict dari perpustakaan standar koleksi modul sebagai alternatif modern yang layak - yang dirancang untuk memecahkan masalah jenis ini.

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 dokumentasi juga menawarkan contoh yang sangat mirip, tetapi menggunakan lambda untuk fungsi pengurutan:

# 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



Ini sering sangat berguna untuk digunakan namedtuple. Misalnya, Anda memiliki kamus 'nama' sebagai kunci dan 'skor' sebagai nilai dan Anda ingin mengurutkan 'skor':

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

menyortir dengan skor terendah lebih dulu:

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

menyortir dengan skor tertinggi lebih dulu:

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

Sekarang Anda bisa mendapatkan nama dan skor, katakanlah pemain terbaik kedua (indeks = 1) sangat Pythonically seperti ini:

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

64
2017-08-30 00:30



Hampir sama dengan jawaban Hank Gay;


    diurutkan ([(nilai, kunci) untuk (kunci, nilai) di mydict.items ()])

Atau dioptimalkan sedikit seperti yang disarankan oleh John Fouhy;


    disortir ((nilai, kunci) untuk (kunci, nilai) di mydict.items ())


57
2018-03-05 01:06