我看了很多并且阅读了很多问题,但是我无法弄清楚如何给sort方法的关键提供两个参数,所以我可以进行更复杂的比较.
例:
class FruitBox():
def __init__(self, weigth, fruit_val):
self.weigth = weigth
self.fruit_val = fruit_val
Run Code Online (Sandbox Code Playgroud)
我想通过fruit_val来比较FruitBox,但是!它们的箱子也比其他箱子大.
所以它会是:
f1 = FruitBox(2,5)
f2 = FruitBox(1,5)
f3 = FruitBox(2,4)
f4 = FruitBox(3,4)
boxes = [f1,f2,f3,f4]
boxes.sort(key = ???) # here is the question
Run Code Online (Sandbox Code Playgroud)
预期结果:
=>[FruitBox(2,4),FruitBox(3,4),FruitBox(1,5),FruitBox(2,5)]
有没有办法发送一个带有2个参数的函数,当我这样做的时候
def sorted_by(a,b):
#logic here, I don't know what will be yet
Run Code Online (Sandbox Code Playgroud)
而我呢
boxes.sort(key=sorted_by)
Run Code Online (Sandbox Code Playgroud)
它抛出:
Traceback (most recent call last):
File "python", line 15, in <module>
TypeError: sort_by_b() missing 1 required positional argument: 'b'
Run Code Online (Sandbox Code Playgroud)
如何给出排序键的两个参数?
这个答案致力于回答:
如何给出排序键的两个参数?
在Python 3中,旧式比较排序方法已经不复存在了,就像在Python 2中一样:
def sorted_by(a,b):
# logic here
pass
boxes.sort(cmp=sorted_by)
Run Code Online (Sandbox Code Playgroud)
但是如果你必须使用Python 3,它仍然存在,但在模块中functool,它的目的是将其转换cmp为key:
import functools
cmp = functools.cmp_to_key(sorted_by)
boxes.sort(key=cmp)
Run Code Online (Sandbox Code Playgroud)
排序的首选方法是创建一个键函数,该函数返回基于排序的权重.见弗朗西斯科的回答.
如果你想使用两个键进行排序,你可以这样做(我想你想先按fruit_val然后排序weight:
boxes.sort(key=lambda x: (x.fruit_val, x.weigth))
Run Code Online (Sandbox Code Playgroud)
文档,关于奇数和结尾的部分说:
该排序程序,保证使用
__lt__()进行比较时两个物体之间。因此,通过定义一个__lt__()方法可以很容易地向一个类添加一个标准的排序顺序。
在您的示例中,转换为将添加__lt__()到您的FruitBox课程中:
class FruitBox():
def __init__(self, weigth, fruit_val):
self.weigth = weigth
self.fruit_val = fruit_val
def __lt__(self, other):
# your arbitrarily complex comparison here:
if self.fruit_val == other.fruit_val:
return self.weight < other.weight
else:
return self.fruit_val < other.fruit_val
# or, as simple as:
return (self.fruit_val, self.weight) < (other.fruit_val, other.weight)
Run Code Online (Sandbox Code Playgroud)
然后像这样简单地使用它:
sorted(fruitbox_objects)
Run Code Online (Sandbox Code Playgroud)