按列表中元素的出现次数对列表进行排序

huk*_*uan 22 python sorting list

我想按列表中元素的出现次数对列表进行排序.
当我使用这个表格时:

A=[2,1,3,4,2,2,3]
A.sort(key=lambda x:A.count(x))  
print(A)
Run Code Online (Sandbox Code Playgroud)

结果不是我想要的:[2, 1, 3, 4, 2, 2, 3].
但是,当我使用sorted以下方式编写时:

B=sorted(A,key=lambda x:A.count(x))
print(B)
Run Code Online (Sandbox Code Playgroud)

结果是对的:[1, 4, 3, 3, 2, 2, 2].
这种行为的原因是什么?

ale*_*cxe 17

这是设计和有意的.CPython暂时"禁止"访问列表,同时对列表进行排序,此行为记录在此处:

CPython实现细节: 在对列表进行排序时,尝试变异甚至检查列表的效果是未定义的.Python的C实现使得列表在持续时间内显示为空,并且如果它可以检测到列表在排序期间已经变异,则会引发ValueError.

您可以通过A在键功能内打印来检查- 您将获得一个空列表:

In [2]: def key_function(x):
    ...:     print(A, x)
    ...:     return A.count(x)
    ...: 

In [3]: A.sort(key=key_function)  
([], 2)
([], 1)
([], 3)
([], 4)
([], 2)
([], 2)
([], 3)
Run Code Online (Sandbox Code Playgroud)

但是,如果你这样做sorted():

In [4]: sorted(A, key=key_function)
([2, 1, 3, 4, 2, 2, 3], 2)
([2, 1, 3, 4, 2, 2, 3], 1)
([2, 1, 3, 4, 2, 2, 3], 3)
([2, 1, 3, 4, 2, 2, 3], 4)
([2, 1, 3, 4, 2, 2, 3], 2)
([2, 1, 3, 4, 2, 2, 3], 2)
([2, 1, 3, 4, 2, 2, 3], 3)
Out[4]: [1, 4, 3, 3, 2, 2, 2]
Run Code Online (Sandbox Code Playgroud)

它也在sort()实现中记录:

/* The list is temporarily made empty, so that mutations performed
 * by comparison functions can't affect the slice of memory we're
 * sorting (allowing mutations during sorting is a core-dump
 * factory, since ob_item may change).
 */.
Run Code Online (Sandbox Code Playgroud)

  • 这不是因为它记录了它不吸吮:) (5认同)
  • 这对我来说听起来不像是一个实现细节. (3认同)
  • 这个限制可能不适用于`key =`函数.我建议在http://bugs.python.org/上提交错误报告 (2认同)
  • 哇!违反最小惊讶原则.一个错误将是一个改进,imo. (2认同)

Jea*_*bre 6

它似乎A在就地排序过程中发生了变化,因此您无法依赖A排序过程中的值.

制作副本也有效.

A=[2,1,3,4,2,2,3]
B=A[:]
A.sort(key=lambda x:B.count(x))
print(A)
Run Code Online (Sandbox Code Playgroud)

python文档中通过这一行确认

CPython实现细节:在对列表进行排序时,尝试变异甚至检查列表的效果是未定义的.Python的C实现使得列表在持续时间内显示为空,并且如果它可以检测到列表在排序期间已经变异,则会引发ValueError.

  • 我不确定这是一个完整的答案,似乎更像一个猜测;) (2认同)