简体   繁体   English

Python字典没有保持秩序

[英]Python dictionary is not staying in order

I created a dictionary of the alphabet with a value starting at 0, and is increased by a certain amount depending on the word file.我创建了一个字母字典,其值从 0 开始,并根据单词文件增加一定数量。 I hard coded the initial dictionary and I wanted it to stay in alphabetical order but it does not at all.我对初始字典进行了硬编码,我希望它保持按字母顺序排列,但根本没有。 I want it to return the dictionary in alphabetical order, basically staying the same as the initial dictionary.我希望它按字母顺序返回字典,基本上与初始字典保持一致。

How can i keep it in order?我怎样才能保持秩序?

from wordData import*

def letterFreq(words):
    
    totalLetters = 0
    letterDict = {'a':0,'b':0,'c':0,'d':0,'e':0,'f':0,'g':0,'h':0,'i':0,'j':0,'k':0,'l':0,'m':0,'n':0,'o':0,'p':0,'q':0,
                  'r':0,'s':0,'t':0,'u':0,'v':0,'w':0,'x':0,'y':0,'z':0}

    for word in words:
        totalLetters += totalOccurences(word,words)*len(word)
        for char in range(0,len(word)):
            for letter in letterDict:
                if letter == word[char]:
                    for year in words[word]:
                        letterDict[letter] += year.count
    for letters in letterDict:
        letterDict[letters] = float(letterDict[letters] / totalLetters)
    print(letterDict)
    return letterDict

def main():
   
    filename = input("Enter filename: ")
    words = readWordFile(filename)
    letterFreq(words)


if __name__ == '__main__':
    main()

Update for Python 3.7+: Python 3.7+ 的更新:

Dictionaries now officially maintain insertion order for Python 3.7 and above.字典现在正式维护Python 3.7 及更高版本的插入顺序


Update for Python 3.6: Python 3.6 更新:

Dictionaries maintain insertion order in Python 3.6, however, this is considered an implementation detail and should not be relied upon .字典在 Python 3.6 中维护插入顺序,但是, 这被视为实现细节,不应依赖


Original answer - up to and including Python 3.5:原始答案 - 直到并包括 Python 3.5:

Dictionaries are not ordered and don't keep any order for you.字典不是有序的,也不会为您保留任何顺序。

You could use an ordered dictionary, which maintains insertion order:您可以使用有序字典,它维护插入顺序:

from collections import OrderedDict
letterDict = OrderedDict([('a', 0), ('b', 0), ('c', 0)])

Or you could just return a sorted list of your dictionary contents或者您可以只返回字典内容的排序列表

letterDict = {'a':0,'b':0,'c':0}
sortedList = sorted([(k, v) for k, v in letterDict.iteritems()])

print sortedList # [('a', 0), ('b', 0), ('c', 0)]

You're only needing the keys in order once, so:您只需要按顺序一次,所以:

# create letterDict as in your question    
keys = list(letterDict)
keys.sort()
for key in keys:
    # do whatever with letterDict[key]

If you needed them in order more than once, you could use the standard library's collections.OrderedDict.如果您不止一次需要它们,您可以使用标准库的 collections.OrderedDict。 Sometimes that's all you need.有时这就是你所需要的。 It preserves dictionary key order by order of addition.它按添加顺序保留字典键顺序。

If you truly need an ordered-by-keys dictionary type, and you don't need it just once (where list_.sort() is better), you could try one of these: http://stromberg.dnsalias.org/~dstromberg/datastructures/如果您真的需要按键排序的字典类型,并且您不需要它一次(其中 list_.sort() 更好),您可以尝试以下方法之一: http ://stromberg.dnsalias.org/ ~dstromberg/数据结构/

With regard to the above link, if your keys are getting added in an already-sorted order, you're probably best off with a treap or red-black tree (a treap is better on average, but red-black trees have a lower standard deviation).关于上面的链接,如果您的键是按已经排序的顺序添加的,那么您可能最好使用 treap 或红黑树(treap 平均更好,但红黑树具有较低的标准差)。 If your keys are (always) getting added in a randomized order, then the simple binary tree is better.如果您的密钥(总是)以随机顺序添加,那么简单的二叉树会更好。

BTW, current fashion seems to favor sorted(list_) over list_.sort(), but sorted(list_) is a relatively recent addition to the language that we got along fine without before it was added, and it's a little slower.顺便说一句,当前的时尚似乎更喜欢 sorted(list_) 而不是 list_.sort(),但是 sorted(list_) 是相对较新的语言添加,在添加之前我们相处得很好,而且速度有点慢。 Also, list_.sort() doesn't give rise to one-liner-abuse the way sorted(list_) does.此外, list_.sort() 不会像 sorted(list_) 那样导致单行滥用。

Oh, and vanilla dictionaries are unordered - that's why they're fast for accessing arbitrary elements (they're built on a hash table).哦,香草词典是无序的——这就是为什么它们可以快速访问任意元素(它们建立在哈希表上)。 Some of the types at datastructures URL I gave above are good at dict_.find_min() and dict_.find_max() and obviate keys.sort(), but they're slower (logn) at accessing arbitrary elements.我在上面给出的数据结构 URL 中的一些类型擅长 dict_.find_min() 和 dict_.find_max() 并避免使用 keys.sort(),但它们在访问任意元素时速度较慢(logn)。

You can sort your dictionary's keys and iterate over your dict.您可以对字典的键进行排序并遍历您的字典。

>>> for key in sorted(letterDict.keys()):
...     print ('{}: {}').format(key, letterDict.get(key))
...
a: 0
b: 0
c: 0
d: 0
e: 0
...

OR或者

This can be a possible solution in your case.在您的情况下,这可能是一个可能的解决方案。 We can have all your dictionary's keys in list whose sequence doesn't change and then we can get values in that order from your dictionary.我们可以将您dictionary's keys所有dictionary's keys放在列表中,其顺序不会改变,然后我们可以从您的字典中按该顺序获取值。

>>> import string
>>> keys = list(string.ascii_lowercase)
>>> letterDict = {'a':0,'b':0,'c':0,'d':0,'e':0,'f':0,'g':0,'h':0,'i':0,'j':0,'k':0,'l':0,'m':0,'n':0,'o':0,'p':0,'q':0,
...                   'r':0,'s':0,'t':0,'u':0,'v':0,'w':0,'x':0,'y':0,'z':0}
>>> for key in keys:
...      if key in letterDict:
...         print ('{}: {}').format(key, letterDict.get(key))
...
a: 0
b: 0
c: 0
d: 0
e: 0
f: 0
g: 0
h: 0
i: 0
j: 0
k: 0
l: 0
m: 0
....

I wouldn't implement it that way.我不会那样实施。 It's pretty hard to read.这很难阅读。 Something more like this:更像这样的东西:

# Make sure that division always gives you a float
from __future__ import division
from collections import defaultdict, OrderedDict
from string import ascii_lowercase

...

    letterDict = defaultdict(int)

    ...

        # Replace the for char in range(0,len(word)): loop with this
        # Shorter, easier to understand, should be equivalent
        for year in words[word]:
            for char in word:
                letterDict[char] += year.count

    ...

    # Filter out any non-letters at this point
    # Note that this is the OrderedDict constructor given a generator that creates tuples
    # Already in order since ascii_lowercase is
    letterRatio = OrderedDict((letter, letterDict[letter] / totalLetters) for letter in ascii_lowercase)
    print(letterRatio)
    return letterRatio

...

Now that you're returning an OrderedDict , the order will be preserved.现在您要返回OrderedDict ,订单将被保留。 I do caution you, though.不过,我确实警告你。 If you really need it to be in order at some point, I would just sort it when you need it in the right order.如果您真的需要在某个时候按顺序排列,我会在您需要时按正确的顺序对其进行排序。 Don't depend on functions that compute new data to return things in a specific sort order.不要依赖计算新数据的函数以特定排序顺序返回事物。 Sort it when you need it sorted, and not before.在需要排序时对其进行排序,而不是之前排序。

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

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