簡體   English   中英

如何在 Python 中對具有鍵作為數字字符串的字典進行排序

[英]How to sort a dictionary having keys as a string of numbers in Python

我有一本字典:

a = {'100':12,'6':5,'88':3,'test':34, '67':7,'1':64 }

我想根據鍵對這本字典進行排序,因此它看起來像:

a = {'1':64,'6':5,'67':7,'88':3, '100':12,'test':34 }

就像其他人指出的那樣,字典有自己的排序方式,您不能像對列表一樣對它們進行排序。

我想補充的一件事是,如果您只想按排序順序瀏覽字典的元素,那就是:

for k in sorted(a):
    print k, a[k] # or whatever.

如果你更喜歡列表理解(按亞歷克斯):

sortedlist = [(k, a[k]) for k in sorted(a)]

我想指出 Alex 對key=int的使用不適用於您的示例,因為您的一個鍵是'test' 如果您真的希望在非數字之前對數字進行排序,則必須傳入一個cmp函數:

def _compare_keys(x, y):
    try:
        x = int(x)
    except ValueError:
        xint = False
    else:
        xint = True
    try:
        y = int(y)
    except ValueError:
        if xint:
            return -1
        return cmp(x.lower(), y.lower())
        # or cmp(x, y) if you want case sensitivity.
    else:
        if xint:
            return cmp(x, y)
        return 1

for k in sorted(a, cmp=_compare_keys):
    print k, a[k] # or whatever.

或者你可能對你的鍵有足夠的了解來編寫一個函數來將它們轉換成一個正確排序的字符串(或其他對象):

# Won't work for integers with more than this many digits, or negative integers.
MAX_DIGITS = 10
def _keyify(x):
    try:
        xi = int(x)
    except ValueError:
        return 'S{0}'.format(x)
    else:
        return 'I{0:0{1}}'.format(xi, MAX_DIGITS)

for k in sorted(a, key=_keyify):
    print k, a[k] # or whatever.

這將比使用cmp函數快得多。

您不能對一個dict作為在Python dict類型本質上是無序的。 您可以做的是在使用sorted()內置函數之前對項目進行sorted() 您還需要一個輔助函數來區分數字鍵和字符串鍵:

def get_key(key):
    try:
        return int(key)
    except ValueError:
        return key
a = {'100':12,'6':5,'88':3,'test':34, '67':7,'1':64 }
print sorted(a.items(), key=lambda t: get_key(t[0]))

但是在 Python 3.1(和 2.7)中, collections模塊包含collections.OrderedDict類型,可用於實現您想要的效果,如下所示:

def get_key(key):
    try:
        return int(key)
    except ValueError:
        return key
a = {'100':12,'6':5,'88':3,'test':34, '67':7,'1':64 }
b = collections.OrderedDict(sorted(a.items(), key=lambda t: get_key(t[0])))
print(b)

9 年前我發布了一個開始食譜

字典無法排序——映射沒有排序!

並展示了如何從字典的鍵和值中獲取排序列表

使用今天的 Python,以及你的表達加隱含規范,我建議:

import sys

def asint(s):
    try: return int(s), ''
    except ValueError: return sys.maxint, s

sortedlist = [(k, a[k]) for k in sorted(a, key=asint)]

key=asint告訴sorted將這些字符串鍵視為整數以進行排序,以便例如'2''1''12'之間排序,而不是在它們之后排序 - 這就是您似乎需要的以及讓所有非全數字鍵在所有全數字鍵之后排序。 如果您還需要處理表示大於 sys.maxint 的整數的全數字鍵字符串,這有點棘手,但仍然可行:

class Infinity(object):
    def __cmp__(self, other): return 0 if self is other else 1
infinite = Infinity()
def asint(s):
    try: return int(s), ''
    except ValueError: return infinite, s

一般來說,如果您從一開始就更准確地指定您的確切要求,您可以更快地獲得更好的答案;-)。

字典是無序的。 你不能像你展示的那樣排序,因為結果a是一個 dict,而 dicts 沒有順序。

如果你想要一個按排序順序列出的鍵列表,你可以使用像這樣的代碼

>>> def my_key(dict_key):
...     try:
...         return int(dict_key)
...     except ValueError:
...         return dict_key
...
>>> sorted(a, key=my_key)
['1', '6', '67', '88', '100', 'test']

這依賴於愚蠢的 Python 行為,即str實例總是大於int實例。 (該行為在 Python 3 中是固定的。)在最佳設計中,您的 dict 的鍵將是您可以合理比較的東西,並且您不會將表示數字的字符串與表示單詞的字符串混合在一起。

如果要保持鍵始終按順序排序,可以使用bisect模塊或實現依賴於樹數據結構的映射。 bisect模塊不接受像排序一樣的key參數,因為這可能效率低下; 如果您選擇使用bisect ,您將使用decorate-use-undecorate 模式,保留一個取決於鍵函數結果的排序列表。

如果你安裝了我的blist包,它包含一個sorteddict類型。 那么你可以簡單地:

from blist import sorteddict

def my_key(dict_key):
       try:
              return int(dict_key)
       except ValueError:
              return dict_key

a = {'100':12,'6':5,'88':3,'test':34, '67':7,'1':64 }
print sorteddict(my_key, **a).keys()

輸出:

['1', '6', '67', '88', '100', 'test']

您還可以做以下事情:

sorted_keys = sorted(list(a.keys()), key = lambda x: (len(x),x))
sorted_dict = {k:a[k] for k in sorted_keys}

最重要的部分是key = lambda x: (len(x),x)我從這里獲取

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM