按Python中出现次数的向量顺序列表

时间:2018-03-26 05:50:21

标签: python list sorting

我试图按特定元素的出现次数排序(反向排序)列表列表。

我已尝试使用后续表达式:

a = [[0,1,0],[1,1,1], [0,1,1]
a.sort(key = (a).count(1) , reverse = True)

所需的输出必须是:

a = [[1,1,1],[0,1,1],[0,1,0]]

但是我收到了错误:

TypeError: 'int' object is not callable

可能,我正在扩展" key"的定义。有没有办法在没有硬编码的情况下完成我在上面尝试的方法并以更加pythonic的方式进行?

5 个答案:

答案 0 :(得分:2)

<% images.each do |image| %> <%= link_to image_url, class: 'fancybox' do%> <%= image_tag image_url(:thumb), id: 'images', :size => "300x300"%> <%end%> <%end%> 参数接受可调用对象,例如功能。您将调用函数的结果传递给参数,该参数将被评估为key

所以,相反,你可以这样做:

int

您的原始尝试表明您正在寻找匿名功能。 Python支持使用def count_key(x): return x.count(1) a = [[0,1,0],[1,1,1], [0,1,1] a.sort(key=count_key, reverse = True) 关键字的匿名函数,这将是一个典型的用例:

lambda

编辑以添加一些测试

快速测试:

a = [[0,1,0],[1,1,1], [0,1,1]
a.sort(key=lambda x: x.count(1), reverse = True)

令人惊讶的是,In [11]: %%timeit import functools; a = 10000*[100*[0,1,0],100*[1,1,1], 100*[0,1,1]] ...: a.sort(key = lambda x: x.count(1), reverse = True) ...: 10 loops, best of 3: 54.7 ms per loop In [12]: %%timeit import functools; a = 10000*[100*[0,1,0],100*[1,1,1], 100*[0,1,1]] ...: a.sort(key = sum, reverse = True) ...: 10 loops, best of 3: 75.1 ms per loop 似乎胜出了。但是,如果内部列表很小,lambda获胜:

sum

现在,有了更大的内部列表,In [16]: %%timeit import functools; a = 10000*[[0,1,0],[1,1,1], [0,1,1]] ...: a.sort(key = lambda x: x.count(1), reverse = True) ...: 100 loops, best of 3: 5.2 ms per loop In [17]: %%timeit import functools; a = 10000*[[0,1,0],[1,1,1], [0,1,1]] ...: a.sort(key = sum, reverse = True) ...: 100 loops, best of 3: 3.82 ms per loop 再次获得优势:

lambda

答案 1 :(得分:2)

In [18]: %%timeit import functools; a = 10000*[1000*[0,1,0],1000*[1,1,1], 1000*[0,1,1]] ...: a.sort(key = lambda x: x.count(1), reverse = True) ...: 1 loop, best of 3: 482 ms per loop In [19]: %%timeit import functools; a = 10000*[1000*[0,1,0],1000*[1,1,1], 1000*[0,1,1]] ...: a.sort(key = sum, reverse = True) ...: 1 loop, best of 3: 679 ms per loop 需要是功能,而不是表达式。

您可以将任何表达式转换为与key一致的函数:

lambda

通常,将功能置于不合适状态会更清楚:

a.sort(key=lambda sublist: sublist.count(1), reverse=True)

...或使用(绑定或未绑定)方法,部分或更高阶函数。像这样:

def countones(lst):
    return lst.count(1)

a.sort(key=countones, reverse=True)

...除了a.sort(key=functools.partial(list.count, value=1), reverse=True) 实际上是一个不带关键字参数的内置函数,所以你不能简单地写它。

在这种情况下,我认为list.count非常明确。

答案 2 :(得分:2)

key参数通过获取可调用并将其应用于列表中的每个元素来确定它应该位于最终排序结果中的位置。

在您的情况下,您传递了a.count(1),在之前评估了 list.sort。在排序时,python将尝试__call__传递的结果(在本例中为0),并且因为int不可调用而失败。如上所述,诀窍是传递一个可调用的。

如果您想传递内联可调用,则需要使用lambda函数:

a.sort(key=lambda x: x.count(1), reverse=True)

否则,在其他答案显示时定义一个函数,并将其作为排序键传递给list.sort

最后,如果您的列表只有0和1,则可以使用key=sum进行微量优化。

a.sort(key=sum, reverse=True)

在这种情况下(假设此情况成立),sum(x)x.count(1)将返回相同的结果。

答案 3 :(得分:1)

最简单的方法是使用lambda函数:

>>> a.sort(key = lambda x: sum(x),reverse = True)
[[1, 1, 1], [0, 1, 1], [0, 1, 0]]

答案 4 :(得分:0)

您也可以尝试:

a = [[0,1,0],[1,1,1], [0,1,1]]
print(sorted(a,key=lambda x:x.count(1),reverse=True))

输出:

[[1, 1, 1], [0, 1, 1], [0, 1, 0]]