如何根据Python字典值的列表长度对其进行排序

5

作为一个人为构造的示例,我有一个类似于以下设置的字典:

{
  'a': ['a', 'b'],
  'b': ['a', 'b', 'c'],
  'c': ['a', 'b', 'c', 'd']
}

我希望按照列表长度(即每个条目的值)的降序对字典进行排序,因此结果应该是这样的:
{
  'c': ['a', 'b', 'c', 'd'],
  'b': ['a', 'b', 'c'],
  'a': ['a', 'b']
}

我曾试图做这样的事情:

sorted_functions = sorted(
  functions.items(),      # Sort the actual items of the dictionary
  key=len(                # Sort on the length of
    operator.itemgetter(  #   the value of the entry, which is
      slice(0, None)      #   a list slice of the whole list
    )
  ),
  reverse=True            # Sort the values in descending order
)

然而,我收到了这个错误:

TypeError: object of type 'operator.itemgetter' has no len()

在 REPL 中,我尝试了以下内容:
>>> d = { 'a': ['a'], 'b': ['a', 'b'] }
>>> itemgetter(slice(0, None))(d['a'])
['a']
>>> len(itemgetter(slice(0, None))(d['a']))
1
>>> itemgetter(slice(0, None))(d['b'])
['a', 'b']
>>> len(itemgetter(slice(0, None))(d['b']))
2

我可以获取列表的长度,但在sorted()函数中,它不起作用。

我需要做什么才能让sorted()函数按照我想要的方式排序?


字典是无序的。 - Daniel Roseman
1
你有什么类型的字典,希望它保留排序顺序? Python的dict根据定义是无序的。您可以使用指定的键len(value)对元素进行排序,但您必须将结果放入列表、SortedDict或其他结构中。 - Prune
1
我知道字典是无序的,但目标是以有序的方式将其写入文件。 - homersimpson
{ k: v for k, v in sorted(d.items(), key=lambda x: len(x[1]), reverse=True) } - ExtractTable.com
请注意,在最后一行中,您对整个表达式调用len - 即在itemgetter的result上调用len - 而在原始代码中,您对itemgetter本身调用len。 - Daniel Roseman
1
@DanielRoseman:Python 3.6+现在支持字典的插入顺序。 - dawg
3个回答

9

使用sortedkey

示例:

d = {
  'a': ['a', 'b'],
  'b': ['a', 'b', 'c'],
  'c': ['a', 'b', 'c', 'd']
}

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

输出:

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

如果想要维护顺序。

import collections
d = collections.OrderedDict(sorted(d.items(), key= lambda x: len(x[1]), reverse=True))
print( d )

啊,我一直在想如何访问整个列表但仍然引用函数而不是值,我考虑使用lambda表达式,但不确定如何在Python中实现,但这绝对有道理。谢谢! - homersimpson
@homersimpson 如果你觉得“使用lambda”很困惑,那么你并不需要。Lambda只是定义一个函数,就像def一样。所以如果你知道你的关键函数要做什么,你可以编写def len_key(item): return len(item[1]),然后像这样使用它:sorted(d.items(), key=len_key) - abarnert
注意:Python 3.6+版本不需要使用OrderedDict。这些版本的字典默认保持插入顺序。 - dawg
@dawg 虽然从技术上讲是正确的,但这是实现特定的事实意味着不应该依赖它。更安全的做法是在3.7之前使用OrderedDict,在那时你的评论将变得普遍准确。 - BowlingHawk95

4

使用OrderedDict

如果你希望你的dict是有序的,你应该使用一个OrderedDict。你可以使用一个key来对第一个dict排序。

代码

from collections import OrderedDict

d = {
  'a': ['a', 'b'],
  'b': ['a', 'b', 'c'],
  'c': ['a', 'b', 'c', 'd']
}

ordered_d = OrderedDict(sorted(d.items(), key=lambda i: -len(i[1])))

print(ordered_d)

输出

OrderedDict([('c', ['a', 'b', 'c', 'd']), ('b', ['a', 'b', 'c']), ('a', ['a', 'b'])])

Python 3.6+的dict是有序的

尽管如此,如果使用Python 3.6+,插入顺序将被保留到dict中。这仅适用于CPython实现,并且仅在3.7版本开始才是官方语言特性

代码

d = {
  'a': ['a', 'b'],
  'b': ['a', 'b', 'c'],
  'c': ['a', 'b', 'c', 'd']
}

ordered_d = dict(sorted(d.items(), key=lambda i: -len(i[1])))

print(ordered_d)

输出

{'c': ['a', 'b', 'c', 'd'], 'b': ['a', 'b', 'c'], 'a': ['a', 'b']}

0

你可以使用 lambda。例如:

my_dict = {
  'a': ['a', 'b'],
  'b': ['a', 'b', 'c'],
  'c': ['a', 'b', 'c', 'd']
}
sorted_list = sorted(my_dict.items(), key= lambda value: len(value[1]), reverse=True) #you will get a sorted list,reverse=True will bring longer lists to appear first
print(sorted_list)
sorted_dict = {x[0]:x[1] for x in sorted_list} #convert your sorted list into dictionary
print(sorted_dict)

或者你可以像Aran-Fey所说的那样,不使用字典推导式来实现:

sorted_dict = dict(sorted_list)

1
你可以用dict(sorted_list) (或更好的是 OrderedDict(sorted_list))来替换字典推导式。 - Aran-Fey
我已经更新了我的答案。感谢您的注意。 - Taohidul Islam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接