繁体   English   中英

如何在Python中按键对字典进行排序

[英]How to sort dictionaries by keys in Python

任何人都可以告诉我如何排序这个:

{'a': [1, 2, 3], 'c': ['one', 'two'], 'b': ['blah', 'bhasdf', 'asdf'], 'd': ['asdf', 'wer', 'asdf', 'zxcv']}

{'a': [1, 2, 3], 'b': ['blah', 'bhasdf', 'asdf'], 'c': ['one', 'two'],'d': ['asdf', 'wer', 'asdf', 'zxcv']}

谢谢!

更新1,代码示例:

所以我在做语言学。 一篇文章分解为存储在数据库中的单词,并具有各种属性,包括段ID和句子ID。 任务:尝试重建原始文本。

从DB中获取500个连续的单词

words = Words.objects.all()[wordId:wordId+500]
# I first create paragraphs, through which I can loop later in my django template,
# and in each para will be a list of words (also dictionaries). 
# So i am trying to get a dictionary with values that are lists of dictionaries. 
# 'pp' i make just for shorthanding a long-named variable.
paras={}
para_high = para_low =  words[0].belongs_to_paragraph
for w in words:
    last_word = w
    pp = w.belongs_to_paragraph
    if pp >para_high:
        para_high = pp
    if pp < para_low:
        para_low = pp
    if pp in paras:
        paras[pp].append(w)
    else:
        list = [w]
        paras[pp] = list
# Since there are blank lines between paragraphs, in rebuilding the text as it 
    #  looked originally, I need to insert blank lines. 
    # Since i have the ID's of the paragraphs and they go somewhat like that: 1,3,4,8,9 
    #(the gaps between 1 & 3 and 4 & 8 i have to fill in with something else, 
    # which is why i had para_low and para_high to loop the range. 
isbr = True
for i in range(para_low, para_high+1):
    if i in paras:
        isbr = True
    else:
        if isbr:
            paras[i]=['break']
            isbr = False
        else:
            paras[i]=[]

但是,在这一点上,如果我尝试循环dict并重建文本,一些后来的id段落在之前的段落之前,那就不会这样做。

更新2,循环代码:

        {% for k,v in wording.iteritems()  %}
        {% if v[0] == 'break' %}
        <br/>
        {% else %}
        </div><div class="p">{% for word in v %}{% if word.special==0%} {% endif %}<span class="word {% if word.special == 0%}clickable{% endif%}" wid="{{word.id}}" special="{{word.special}}" somethingElse={{word.somethingElse}}>{{ word.word }}</span>{% endfor %}
        {% endif %}
    {% endfor %}

Dicts没有订单。

你可以调用sorted,但这只是给你一个键的排序列表:

>>> sorted(d)
['a', 'b', 'c', 'd']

您可以将其视为可迭代的并对键值元组进行排序,但之后您就会得到一个元组列表。 这和dict不一样。

>>> sorted(d.items())
[
 ('a', [1, 2, 3]),
 ('b', ['blah', 'bhasdf', 'asdf']),
 ('c', ['one', 'two']),
 ('d', ['asdf', 'wer', 'asdf', 'zxcv'])
]

如果您使用的是Python 2.7或更高版本,您还可以考虑使用OrderedDict

记住订单条目的dict子类已添加

例如:

>>> d = collections.OrderedDict(sorted(d.items()))
>>> for k, v in d.items():
>>>     print k, v
a [1, 2, 3]
b ['blah', 'bhasdf', 'asdf']
c ['one', 'two']
d ['asdf', 'wer', 'asdf', 'zxcv']

正确答案是,如果您希望按排序顺序排列字典,则在循环字典时应使用sorted()函数:

for k, v in sorted(d.items()):
    print k, ':', v

要么

for k in sorted(d):
   print d[k]

或类似的。

提到的OrderedDict适用于有订单的字典。 订单与排序不一样。 您可以创建一个已排序的OrderedDict,但是,只要添加新密钥,就不再对其进行排序。 所以你需要在每次使用之前或每次操作之后使用sorted()进行排序。 因此,OrderedDict只比普通字典更慢,占用内存更多,同时不需要添加任何内容。

OrderedDict 不适用于已排序的词典,但适用于字典,其中项目具有某种不是排序的排序。 例如,如果您想按照添加的顺序显示内容,或者您​​希望用户能够任意订购内容。

更新:进一步说明

为什么OrderedDict不是解决方案? 因为订购的OrderedDict没有排序

考虑一个标准字典:

>>> d = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5}

它没有排序,如下所示,'c'将在'b'之前出现。 它也没有订单,如果我们添加新的东西,它看起来像是随机顺序:

>>> d['g'] = 6
>>> d['i'] = 8
>>> d
{'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': 6, 'f': 5, 'i': 8}

好的,那么让我们使用OrderedDict:

>>> o = OrderedDict(sorted({'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5}.items()))
>>> o
OrderedDict([('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4), ('f', 5)])

啊哈! 排序! 所以OrderedDict有效!? 没有。

>>> o['i'] = 8
>>> o['g'] = 6
>>> o
OrderedDict([('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4), ('f', 5), ('i', 8), ('g', 6)])

什么? 在我之后 ,g结束了吗?!? 为什么!? 因为OrderedDict没有排序,所以它是有序的 它会记住你添加东西的顺序 不是排序。 这意味着每次使用它时都需要先对其进行排序。 只要您不向其添加密钥,OrderedDict将仅保持排序。 但如果你不打算修改它,那么你就不需要dict了。 你也可以有一个清单。 这是你从sorted()得到的:

>>> sorted(o.items())
[('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4), ('f', 5), ('g', 6), ('i', 8)]

但是这与标准字典一样有效,所以OrderedDictionary没有帮助:

>>> sorted(d.items())
[('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4), ('f', 5), ('g', 6), ('i', 8)]

结束语因此,每次要以排序方式遍历字典时,都需要执行以下操作:

>>> for k in sorted(o):
...   print k, o[k]
... 
a 0
b 1
c 2
d 3
e 4
f 5
g 6
i 8

这就是你使用的字典 OrderedDict并没有真正帮助你,因为它不关心排序 ,只关心你添加内容的顺序

值得注意的是,Python有许多字典实现,可以按排序顺序维护密钥。 考虑sortedcontainers模块,它是纯Python和快速实现的C实现。 与其他快速和功能完备的实现进行性能比较

例如:

>>> from sortedcontainers import SortedDict
>>> d = {'a': [1, 2, 3], 'c': ['one', 'two'], 'b': ['blah', 'bhasdf', 'asdf'], 'd': ['asdf', 'wer', 'asdf', 'zxcv']}
>>> s = SortedDict(**d)
>>> s.keys()
SortedSet(['a', 'b', 'c', 'd'])

您还可以完全用SortedDict替换您对dict的使用,因为它支持快速获取/设置操作以及按键排序的项目迭代。

正如另一个答案所提到的,字典键的顺序是任意的,你不应该依赖它。

如果你使用的是Python 2.7或3.1或更高版本,请试用collections.OrderedDict2.7 docs ; 3.1 docs ;另见PEP 372 )。 文档中有一个链接到纯Python版的OrderedDict ,它适用于早期的Python版本。

这是一个快速简便的功能,您可以使用按键对字典进行排序。

将此代码放在名为sdict.py的单独文件中:

def sortdict(dct):
    kys = dct.keys()
    kys.sort()
    from collections import OrderedDict
    d = OrderedDict()
    for x in kys: 
        for k, v in dct.iteritems():
            if (k == x):
                d[k] = v
    return d

现在,将此代码放入一个名为test.py的单独文件中,以使用示例字典对其进行测试:

from sdict import sortdict
import json
dct = {'sizes':[32,28,42], 'dog':'schnauser', 'cat':'siamese', 'bird':'falcon'}
dctx = sortdict(dct)
print json.dumps(dctx) 

最后,从命令行调用test.py

$ python test.py
{"bird": "falcon", "cat": "siamese", "dog": "schnauser", "sizes": [32, 28, 42]}

我只使用json.dumps行来向您显示它是一个真正的字典,而不仅仅是字符串表示。 您也可以使用type()函数对其进行测试。

我在示例字典中包含了一个带有数值的嵌套列表,以显示该函数可以处理更复杂的字典,而不仅仅是单层基于字符串的字典。

代码非常简单,因此很容易修改它以按值排序,如果这是您的偏好 - 尽管如果某些值是对象(如列表,元组或其他dicts),按值排序是没有意义的。

不可否认,这只适用于python 2.7或更高版本。

干杯,
- =卡梅伦

也许值得一提的是heapq中的最大例程。 这将排序并返回前N个项目。 根据实际需要,如果您使用关键参数,这可能很方便。 自从几天前我发现它之后,我主要提到这一点,它完全按照我的目标行事。 PEP 0265Heapq

我将把我的一分钱加到其他已经解释过的内容上。 在一个特定情况下,我碰巧遇到了完全相同的问题。 我需要字典的输出始终与编写稳定的单元测试相同。

如果碰巧是你想要实现的,或者其他与输出相关的任务,你根本不需要排序任何东西,只需使用pprint模块,除了其他功能之外,它还会按键对字典进行排序。

>>> d = {'a':1, 'b':2, 'c':3}
>>> print d
{'a': 1, 'c': 3, 'b': 2}

>>> from pprint import pprint
>>> pprint(d)
{'a': 1, 'b': 2, 'c': 3}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM