我试图按特定元素的出现次数排序(反向排序)列表列表。
我已尝试使用后续表达式:
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的方式进行?
答案 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]]