如何在Python中将具有键的字典排序为一串数字

时间:2010-03-30 19:17:30

标签: 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 }

5 个答案:

答案 0 :(得分:12)

正如其他人所指出的那样,词典有自己的排序,你不能像对待列表一样对它们进行排序。

我想补充的一点是,如果您只想按排序顺序浏览字典的元素,那就是:

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

如果你更喜欢列表理解(每个Alex):

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函数要快得多。

答案 1 :(得分:6)

您无法在Python中对dict进行排序,因为dict类型本质上是无序的。您可以做的是在使用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)

答案 2 :(得分:5)

9年前,我发布了启动<{em>

recipe
  

无法对字典进行排序 - a   映射没有排序!

并显示如何从字典的键和值中排序列表

使用今天的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

一般情况下,如果从一开始就更准确地指定确切的要求,就可以更快地得到更好的答案。 - )。

答案 3 :(得分:4)

字典无序。你不能像你所显示的那样对它进行排序,因为结果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模式,保留一个取决于键函数结果的排序列表。

答案 4 :(得分:2)

如果您安装了我的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']