首页 文章

如何按值对字典进行排序?

提问于
浏览
3136

我有一个从数据库中的两个字段读取的值字典:字符串字段和数字字段 . 字符串字段是唯一的,因此这是字典的关键字 .

我可以对键进行排序,但是如何根据值进行排序?

注意:我已阅读Stack Overflow问题How do I sort a list of dictionaries by values of the dictionary in Python?,可能会更改我的代码以获得字典列表,但由于我不需要字典列表,我想知道是否有更简单的解决方案 .

30 回答

  • 3773

    您还可以使用可以传递给密钥的自定义函数 .

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

    您可以使用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() ,那么您将按值排序 .

    它是使用skip list数据结构实现的 .

  • 6

    在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-recipes

    请享用 ;-)

  • 18

    你可以使用:

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

    这将根据字典中从最小到最大的每个条目的值对字典进行排序 .

  • 23

    不可能对字典进行排序,只是为了获得已排序的字典的表示 . 字典本质上是无序的,但其他类型(如列表和元组)则不是 . 因此,您需要一个有序数据类型来表示排序值,这将是一个列表 - 可能是元组列表 .

    例如,

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

    UPDATE: 5 DECEMBER 2015 using Python 3.5

    虽然我发现接受的答案很有用,但我也感到惊讶的是,它尚未更新为从标准库 collections 模块引用 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)])
    
  • 180

    我想出了这个,

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

    如果您的值是整数,并且您使用的是Python 2.7或更高版本,则可以使用collections.Counter而不是 dict . most_common 方法将为您提供按值排序的所有项目 .

  • 637

    这是代码:

    import operator
    origin_list = [
        {"name": "foo", "rank": 0, "rofl": 20000},
        {"name": "Silly", "rank": 15, "rofl": 1000},
        {"name": "Baa", "rank": 300, "rofl": 20},
        {"name": "Zoo", "rank": 10, "rofl": 200},
        {"name": "Penguin", "rank": -1, "rofl": 10000}
    ]
    print ">> Original >>"
    for foo in origin_list:
        print foo
    
    print "\n>> Rofl sort >>"
    for foo in sorted(origin_list, key=operator.itemgetter("rofl")):
        print foo
    
    print "\n>> Rank sort >>"
    for foo in sorted(origin_list, key=operator.itemgetter("rank")):
        print foo
    

    结果如下:

    Original

    {'name': 'foo', 'rank': 0, 'rofl': 20000}
    {'name': 'Silly', 'rank': 15, 'rofl': 1000}
    {'name': 'Baa', 'rank': 300, 'rofl': 20}
    {'name': 'Zoo', 'rank': 10, 'rofl': 200}
    {'name': 'Penguin', 'rank': -1, 'rofl': 10000}
    

    Rofl

    {'name': 'Baa', 'rank': 300, 'rofl': 20}
    {'name': 'Zoo', 'rank': 10, 'rofl': 200}
    {'name': 'Silly', 'rank': 15, 'rofl': 1000}
    {'name': 'Penguin', 'rank': -1, 'rofl': 10000}
    {'name': 'foo', 'rank': 0, 'rofl': 20000}
    

    Rank

    {'name': 'Penguin', 'rank': -1, 'rofl': 10000}
    {'name': 'foo', 'rank': 0, 'rofl': 20000}
    {'name': 'Zoo', 'rank': 10, 'rofl': 200}
    {'name': 'Silly', 'rank': 15, 'rofl': 1000}
    {'name': 'Baa', 'rank': 300, 'rofl': 20}
    
  • 82

    您也可以创建“倒排索引”

    from collections import defaultdict
    inverse= defaultdict( list )
    for k, v in originalDict.items():
        inverse[v].append( k )
    

    现在您的逆值具有值;每个值都有一个适用键列表 .

    for k in sorted(inverse):
        print k, inverse[k]
    
  • 62

    从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年提出(参见主题为"More compact dictionaries with faster iteration"的python-dev上的邮件),现在(2016年)由Victor Stinner发送邮件至主题为"Python 3.6 dict becomes compact and gets a private version; and keywords become ordered"的python-dev,由于问题27350 "Compact and ordered dict"的修复/实施Python 3.6我们现在可以使用内置的dict来维护插入顺序!!

    希望这将导致薄层OrderedDict实现作为第一步 . 正如@ JimFasarakis-Hilliard所指出的那样,有些人在未来也会看到OrderedDict类型的用例 . 我认为整个Python社区将仔细检查,如果这将经得起时间的考验,以及接下来的步骤将是什么 .

    是时候重新考虑我们的编码习惯,不要错过稳定订购的可能性:

    • 关键字参数和

    • (中间)dict存储

    第一个是因为它在某些情况下简化了函数和方法实现中的调度 .

    第二,因为它鼓励更容易使用 dict 作为处理管道的中间存储 .

    Raymond Hettinger在他的旧金山Python Meetup Group演讲2016-DEC-08上提供了解释“The Tech Behind Python 3.6 Dictionaries”的文档 .

    也许相当一些Stack Overflow高度装饰的问答页面将收到此信息的变体,许多高质量的答案也需要每个版本更新 .

    告诫Emptor(还见下面更新2017-12-15):

    正如@ajcr正确地指出:"The order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon."(来自whatsnew36)没有采摘, but 的引文被削减了一点悲观;-) . 它继续作为" (this may change in the future, but it is desired to have this new dict implementation in the language for a few releases before changing the language spec to mandate order-preserving semantics for all current and future Python implementations; this also helps preserve backwards-compatibility with older versions of the language where random iteration order is still in effect, e.g. Python 3.5)."

    因此,在某些人类语言(例如德语)中,用法形成语言,现在已经存在声明......在whatsnew36 .

    更新2017-12-15:

    mail to the python-dev list,Guido van Rossum宣布:

    这样做 . “Dict保持插入秩序”是裁决 . 谢谢!

    因此,dict插入排序的版本3.6 CPython副作用现在正成为语言规范的一部分(而不再仅仅是实现细节) . 正如Raymond Hettinger在讨论中提醒的那样,该邮件线程也为 collections.OrderedDict 提出了一些明显的设计目标 .

  • 67

    尝试以下方法 . 让我们用以下数据定义一个名为mydict的字典:

    mydict = {'carl':40,
              'alan':2,
              'bob':1,
              'danny':3}
    

    如果想要按键对字典进行排序,可以执行以下操作:

    for key in sorted(mydict.iterkeys()):
        print "%s: %s" % (key, mydict[key])
    

    这应该返回以下输出:

    alan: 2
    bob: 1
    carl: 40
    danny: 3
    

    另一方面,如果想按值对字典进行排序(如问题中所述),可以执行以下操作:

    for key, value in sorted(mydict.iteritems(), key=lambda (k,v): (v,k)):
        print "%s: %s" % (key, value)
    

    此命令的结果(按值对字典排序)应返回以下内容:

    bob: 1
    alan: 2
    danny: 3
    carl: 40
    
  • 15

    这将返回字典中键值对的列表,按值从最高到最低排序:

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

    对于按键排序的字典,请使用以下内容:

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

    返回是元组列表,因为字典本身无法排序 .

    这可以打印或发送到进一步的计算中 .

  • 22

    这是在d.values() and 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')]
    
  • 58

    使用 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
    
  • 41

    如果值是数字,您还可以使用集合中的计数器

    from collections import Counter
    
    x={'hello':1,'python':5, 'world':3}
    c=Counter(x)
    print c.most_common()
    
    
    >> [('python', 5), ('world', 3), ('hello', 1)]
    
  • 12

    使用dicts来自dicts

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

    Dicts无法排序,但您可以从中构建排序列表 .

    dict值的排序列表:

    sorted(d.values())
    

    按键排序的(键,值)对列表:

    from operator import itemgetter
    sorted(d.items(), key=itemgetter(1))
    
  • 9

    As pointed out by Dilettant,Python 3.6现在会保留订单!我以为我会共享一个我编写的函数,它可以简化迭代(元组,列表,字典)的排序 . 在后一种情况下,您可以对键或值进行排序,也可以将数值比较考虑在内 . Only for >= 3.6!

    当你尝试在一个包含例如的迭代时使用sorted字符串以及整数,sorted()将失败 . 当然你可以用str()强制进行字符串比较 . 但是,在某些情况下,您希望进行实际的数字比较,其中 12 小于 20 (在字符串比较中不是这种情况) . 所以我想出了以下内容 . 当您想要显式数字比较时,您可以使用标志 num_as_num ,它将尝试通过尝试将所有值转换为浮点数来进行显式数字排序 . 如果成功,它将进行数字排序,否则它将采用字符串比较 .

    评论改进或push requests欢迎 .

    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")
    
  • 6

    在最近的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)])
    
  • 13

    鉴于字典

    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函数按值对事物进行排序,并将它们存储在变量中,在这种情况下 srede 原始字典 .

    希望有所帮助!

  • 137
    from django.utils.datastructures import SortedDict
    
    def sortedDictByKey(self,data):
        """Sorted dictionary order by key"""
        sortedDict = SortedDict()
        if data:
            if isinstance(data, dict):
                sortedKey = sorted(data.keys())
                for k in sortedKey:
                    sortedDict[k] = data[k]
        return sortedDict
    
  • 37

    您可以使用Python的排序函数

    sorted(iterable[, cmp[, key[, reverse]]])

    因此你可以使用:

    sorted(dictionary.items(),key = lambda x :x[1])

    有关排序功能的更多信息,请访问此链接:https://docs.python.org/2/library/functions.html#sorted

  • 20

    从技术上讲,字典不是序列,因此无法排序 . 你可以做点什么

    sorted(a_dictionary.values())
    

    假设表现不是很大 .

  • 19

    当然,请记住,您需要使用 OrderedDict ,因为常规Python词典不保留原始顺序 .

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

    如果您没有Python 2.7或更高版本,那么您可以做的最好是迭代生成器函数中的值 . (2.4和2.6 here有一个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或更高版本,请记得在打印后删除括号

  • 18

    简单如下:sorted(dict1,key = dict1.get)

    嗯,实际上可以做一个"sort by dictionary values" . 最近我必须在Code Golf(Stack Overflow问题Code golf: Word frequency chart)中这样做 . 简而言之,问题就是那种:给定一个文本,计算每个单词遇到和显示的频率顶部单词列表,按降频排序 .

    如果构造一个字典,其中单词为键,每个单词的出现次数为值,则简化为:

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

    然后你可以得到一个单词列表,按照使用频率排序 sorted(d, key=d.get) - 排序迭代字典键,使用单词出现次数作为排序键 .

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

    我正在写这个详细的解释,以说明人们通常所说的“我可以轻松地按键排序字典,但我如何按 Value 排序” - 我认为OP试图解决这个问题 . 解决方案是根据值对键进行排序,如上所示 .

  • 6

    我遇到了同样的问题,我这样解决了:

    WantedOutput = sorted(MyDict, key=lambda x : MyDict[x])
    

    (回答“不可能对词典进行排序”的人没有读到这个问题!事实上,“我可以对键进行排序,但是如何根据值进行排序?”显然意味着他想要一个列表键根据其值的值排序 . )

    请注意,订单定义不明确(具有相同值的键将在输出列表中以任意顺序排列) .

  • 14

    与Hank Gay的回答几乎相同;

    sorted([(value,key) for (key,value) in mydict.items()])
    

    或者根据John Fouhy的建议进行优化;

    sorted((value,key) for (key,value) in mydict.items())
    
  • 7

    你可以使用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)])
    
  • 5

    迭代一个字典并按其值按降序排序:

    $ 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
    

相关问题