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

时间:2017-02-03 14:31:58

标签: python list sorting

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

A=[2,1,3,4,2,2,3]
A.sort(key=lambda x:A.count(x))  
print(A)

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

B=sorted(A,key=lambda x:A.count(x))
print(B)

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

4 个答案:

答案 0 :(得分:17)

这是设计和有意的。 CPython暂时"不允许"在对列表进行排序时访问列表,行为为documented here

  

CPython实现细节: 在对列表进行排序时,   试图改变甚至检查清单的效果是   undefined。 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)

但是,如果你为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]

它还记录在sort() implementation

/* 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).
 */.

答案 1 :(得分:6)

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

制作副本也有效。

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

python documentation

中的这一行确认
  

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

答案 2 :(得分:2)

我相信它是因为A.sort在计算时正在修改下面的列表。 sorted()不修改列表并返回正确的结果。

答案 3 :(得分:1)

内置sorted creates a list out of the sequence提供然后根据键参数对其进行排序(省略错误检查):

/* copy sequence provided */
newlist = PySequence_List(seq);

/* get list.sort for the list object */
callable = _PyObject_GetAttrId(newlist, &PyId_sort);

/* call it and then return later on */
v = _PyObject_FastCallKeywords(callable, args + 1, nargs - 1, kwnames);

这实际上转化为Jean在答案中提供的内容:

B = list(A)
B.sort(key=lambda x: A.count(x))

通过在B函数中复制A并引用key,可以消除A.sort强加的限制,而这种限制本身无法查看。