python辭典 - sort字典python




如何按值對字典進行排序? (20)

Python 3.6開始 ,內置的dict將被訂購

好消息,所以OP的原始用例是從具有唯一字符串ID的數據庫中檢索到的映射對作為鍵和數值作為值到內置Python v3.6 + dict,現在應該遵循插入順序。

如果說從數據庫查詢得到的兩個列表表達式如下:

SELECT a_key, a_value FROM a_table ORDER BY a_value;

將存儲在兩個Python元組中,k_seq和v_seq(由數字索引對齊,當然長度相同),然後:

k_seq = ('foo', 'bar', 'baz')
v_seq = (0, 1, 42)
ordered_map = dict(zip(k_seq, v_seq))

允許稍後輸出為:

for k, v in ordered_map.items():
    print(k, v)

在這種情況下產生(對於新的Python 3.6+內置字典!):

foo 0
bar 1
baz 42

每個v值相同的排序。

在我的機器上安裝Python 3.5的地方,它目前產生:

bar 1
foo 0
baz 42

細節:

正如Raymond Hettinger在2012年提出的那樣(參見python-dev上的郵件主題為“更緊湊的詞典和更快速的迭代” ),現在(2016年)由Victor Stinner在郵件中宣布python-dev主題為“Python 3.6 dict”緊湊並獲得私有版本;關鍵字變得有序“由於問題27350的修復/實現”緊湊和有序的dict“在Python 3.6中我們現在可以使用內置的dict來維護插入順序!!

希望這將導致薄層OrderedDict實現作為第一步。 正如@ JimFasarakis-Hilliard所指出的那樣,有些人在未來也會看到OrderedDict類型的用例。 我認為整個Python社區將仔細檢查,如果這將經得起時間的考驗,以及接下來的步驟將是什麼。

是時候重新考慮我們的編碼習慣,不要錯過穩定訂購的可能性:

  • 關鍵字參數和
  • (中間)dict存儲

第一個是因為它在某些情況下簡化了函數和方法實現中的調度。

第二,因為它鼓勵更容易使用dict作為處理管道的中間存儲。

Raymond Hettinger在他的舊金山Python Meetup Group演講2016-DEC-08上提供了解釋“ Python 3.6 Dictionaries背後的技術文檔。

也許相當一些Stack Overflow高度裝飾的問答頁面將收到此信息的變體,許多高質量的答案也需要每個版本更新。

警告Empat(但也見下面更新2017-12-15):

正如@ajcr正確地指出:“這個新實現的順序保留方面被認為是一個實現細節,不應該依賴它。” (來自whatsnew36 )沒有採摘, 引用被削減了一點悲觀;-)。 它繼續作為“(這可能在未來發生變化,但是在更改語言規範之前,希望在幾種版本的語言中使用這個新的dict實現,以便為所有當前和未來的Python實現強制保持語義保持語義;這也是有助於保持與隨機迭代順序仍然有效的語言的舊版本的向後兼容性,例如Python 3.5)。“

因此,在一些人類語言(例如德語)中,用法形成了語言,現在已經在whatsnew36中聲明了...

更新2017-12-15:

發往python-dev列表郵件中 ,Guido van Rossum宣稱:

這樣做。 “Dict保持插入秩序”是裁決。 謝謝!

因此,dict插入排序的版本3.6 CPython副作用現在正成為語言規範的一部分(而不再僅僅是實現細節)。 該郵件線程也為collections.OrderedDict一些明顯的設計目標。訂購時,Raymond Hettinger在提及討論時提到了訂單。

我有一個從數據庫中的兩個字段讀取的值字典:字符串字段和數字字段。 字符串字段是唯一的,因此這是字典的關鍵字。

我可以對鍵進行排序,但是如何根據值進行排序?

注意:我已閱讀Stack Overflow問題如何按Python中字典的值對字典列表進行排序? 並且可能會改變我的代碼以獲得字典列表,但由於我不需要字典列表,我想知道是否有更簡單的解決方案。


很簡單: sorted(dict1, key=dict1.get)

嗯,實際上可以做一個“按字典值排序”。 最近我必須在Code Golf(問題代碼高爾夫:Word頻率圖表 )中這樣做。 簡而言之,問題就是這樣:給定一個文本,計算每個單詞遇到的頻率,並顯示頂部單詞列表,按頻率降低排序。

如果構造一個字典,其中單詞為鍵,每個單詞的出現次數為值,則簡化為:

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

然後你可以得到一個單詞列表,按使用頻率sorted(d, key=d.get)sorted(d, key=d.get) - 排序迭代字典鍵,使用單詞出現次數作為排序鍵。

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

我正在寫這個詳細的解釋,以說明人們通常所說的“我可以輕鬆地按鍵排序字典,但我如何按價值排序” - 我認為OP試圖解決這個問題。 解決方案是根據值對鍵進行排序,如上所示。


更新:2015年12月5日使用Python 3.5

雖然我發現接受的答案很有用,但我也感到驚訝的是它沒有更新為從標準庫集合模塊引用OrderedDict作為一種可行的,現代的替代方案 - 旨在解決這類問題。

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

官方的OrderedDict文檔也提供了一個非常相似的例子,但是使用lambda作為sort函數:

# 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)])

不可能對字典進行排序,只是為了獲得已排序的字典的表示。 字典本質上是無序的,但其他類型(如列表和元組)則不是。 因此,您需要一個有序數據類型來表示排序值,這將是一個列表 - 可能是元組列表。

例如,

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

sorted_x將是由每個元組中的第二個元素排序的元組列表。 dict(sorted_x) == x

對於那些希望按鍵而不是值進行排序的人:

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

在Python3中,因為不允許解包[1]我們可以使用

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

使用namedtuple通常非常方便。 例如,您有一個'name'字典作為鍵,'score'作為值,您想要對'score'進行排序:

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

首先排序得分最低:

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

首先排序得分最高:

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

現在你可以得到名字和得分,讓我們說第二好的球員(指數= 1)非常像這樣:

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

使用來自dicts的ValueSortedDict

from dicts.sorteddict import ValueSortedDict
d = {1: 2, 3: 4, 4:3, 2:1, 0:0}
sorted_dict = ValueSortedDict(d)
print sorted_dict.items() 

[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]

在Python 2.7中,只需執行以下操作:

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

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

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

複製粘貼來自: http://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipeshttp://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes

請享用 ;-)


在最近的Python 2.7中,我們有了新的OrderedDict類型,它記住了項目的添加順序。

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

要從原始字典創建新的有序字典,請按值排序:

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

OrderedDict的行為類似於普通的dict:

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

如果您的值是整數,並且您使用的是Python 2.7或更高版本,則可以使用collections.Counter而不是dictmost_common方法將為您提供按值排序的所有項目。


從技術上講,字典不是序列,因此無法排序。 你可以做點什麼

sorted(a_dictionary.values())

假設表現不是很大。


您可以使用collections.Counter 。 請注意,這適用於數字和非數字值。

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> from collections import Counter
>>> #To sort in reverse order
>>> Counter(x).most_common()
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> Counter(x).most_common()[::-1]
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
>>> #To get a dictionary sorted by values
>>> from collections import OrderedDict
>>> OrderedDict(Counter(x).most_common()[::-1])
OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

您可以使用skip dict ,它是一個按值永久排序的字典。

>>> data = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> SkipDict(data)
{0: 0.0, 2: 1.0, 1: 2.0, 4: 3.0, 3: 4.0}

如果您使用keys()values()items()那麼您將按值排序。

它是使用跳過列表數據結構實現的。


您還可以使用可以傳遞給鍵的自定義函數。

def dict_val(x):
    return x[1]
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=dict_val)

還有一種方法是使用labmda函數

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

我想出了這個,

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

對於Python 3.x: x.items()替換iteritems()

>>> sorted_x
{0: 0, 1: 2, 2: 1, 3: 4, 4: 3}

或嘗試使用collections.OrderedDict

x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
from collections import OrderedDict

od1 = OrderedDict(sorted(x.items(), key=lambda t: t[1]))

正如Dilettant所指出的 ,Python 3.6現在將保持訂單 ! 我以為我會共享一個我編寫的函數,它可以簡化迭代(元組,列表,字典)的排序。 在後一種情況下,您可以對鍵或值進行排序,也可以將數值比較考慮在內。 僅適用於> = 3.6!

當您嘗試在包含例如字符串和整數的迭代上使用sorted時,sorted()將失敗。 當然你可以用str()強制進行字符串比較。 但是,在某些情況下,您希望進行實際數值比較,其中12小於20 (在字符串比較中不是這種情況)。 所以我想出了以下內容。 當您想要顯式數字比較時,您可以使用標誌num_as_num ,它將嘗試通過嘗試將所有值轉換為浮點數來進行顯式數字排序。 如果成功,它將進行數字排序,否則它將採用字符串比較。

歡迎評論改進或推送請求

def sort_iterable(iterable, sort_on=None, reverse=False, num_as_num=False):
    def _sort(i):
      # sort by 0 = keys, 1 values, None for lists and tuples
      try:
        if num_as_num:
          if i is None:
            _sorted = sorted(iterable, key=lambda v: float(v), reverse=reverse)
          else:
            _sorted = dict(sorted(iterable.items(), key=lambda v: float(v[i]), reverse=reverse))
        else:
          raise TypeError
      except (TypeError, ValueError):
        if i is None:
          _sorted = sorted(iterable, key=lambda v: str(v), reverse=reverse)
        else:
          _sorted = dict(sorted(iterable.items(), key=lambda v: str(v[i]), reverse=reverse))

      return _sorted

    if isinstance(iterable, list):
      sorted_list = _sort(None)
      return sorted_list
    elif isinstance(iterable, tuple):
      sorted_list = tuple(_sort(None))
      return sorted_list
    elif isinstance(iterable, dict):
      if sort_on == 'keys':
        sorted_dict = _sort(0)
        return sorted_dict
      elif sort_on == 'values':
        sorted_dict = _sort(1)
        return sorted_dict
      elif sort_on is not None:
        raise ValueError(f"Unexpected value {sort_on} for sort_on. When sorting a dict, use key or values")
    else:
      raise TypeError(f"Unexpected type {type(iterable)} for iterable. Expected a list, tuple, or dict")

當然,請記住,您需要使用OrderedDict因為常規Python字典不保留原始順序。

from collections import OrderedDict
a = OrderedDict(sorted(originalDict.items(), key = lambda x: x[1]))

如果您沒有Python 2.7或更高版本,那麼您可以做的最好是迭代生成器函數中的值。 (這裡有2.4和2.6的OrderedDict,但是

a) I don't know about how well it works 

b) You have to download and install it of course. If you do not have administrative access, then I'm afraid the option's out.)
def gen(originalDict):
    for x,y in sorted(zip(originalDict.keys(), originalDict.values()), key = lambda z: z[1]):
        yield (x, y)
    #Yields as a tuple with (key, value). You can iterate with conditional clauses to get what you want. 

for bleh, meh in gen(myDict):
    if bleh == "foo":
        print(myDict[bleh])

您還可以打印出每個值

for bleh, meh in gen(myDict):
    print(bleh,meh)

如果不使用Python 3.0或更高版本,請記得在打印後刪除括號


迭代一個字典並按其值按降序排序:

$ python --version
Python 3.2.2

$ cat sort_dict_by_val_desc.py 
dictionary = dict(siis = 1, sana = 2, joka = 3, tuli = 4, aina = 5)
for word in sorted(dictionary, key=dictionary.get, reverse=True):
  print(word, dictionary[word])

$ python sort_dict_by_val_desc.py 
aina 5
tuli 4
joka 3
sana 2
siis 1

這將返回字典中鍵值對的列表,按值從最高到最低排序:

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

對於按鍵排序的字典,請使用以下內容:

sorted(d.items(), reverse=True)

返回是元組列表,因為字典本身無法排序。

這可以打印或發送到進一步的計算中。


這是在d.values()d.keys()上使用zip的解決方案。 此鏈接的幾行(在Dictionary視圖對像上)是:

這允許使用zip()創建(值,鍵)對:pairs = zip(d.values(),d.keys())。

所以我們可以做到以下幾點:

d = {'key1': 874.7, 'key2': 5, 'key3': 8.1}

d_sorted = sorted(zip(d.values(), d.keys()))

print d_sorted 
# prints: [(5, 'key2'), (8.1, 'key3'), (874.7, 'key1')]

鑑於字典

e = {1:39, 4:34, 7:110, 2:87}

排序

sred = sorted(e.items(), key=lambda value: value[1])

結果

[(4, 34), (1, 39), (2, 87), (7, 110)]

您可以使用lambda函數按值對事物進行排序,並將它們存儲在變量中,在本例中使用原始字典進行sred

希望有所幫助!





dictionary