为什么 sort(with key) 函数不能按预期工作?
why does the sort(with key) function not work as intended?
# A function that returns the frequency of each value:
def myFunc(e):
return cars.count(e)
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi','Mitsubishi', 'BMW', 'VW']
cars.sort(key=myFunc)
print(cars)
输出:
['Ford', 'Ford', 'Ford', 'Mitsubishi', 'Mitsubishi', 'BMW', 'VW']
我的期望:
['BMW', 'VM', 'Mitsubishi', 'Mitsubishi', 'Ford', 'Ford', 'Ford']
计数:
Ford - 3
Mitsubishi - 2
BMW - 1
VM - 1
它应该按列表中计数的升序排序。
问题是您在关键函数中使用了 cars
,但是 .sort
是 in-place。这导致 cars
在对关键函数的中间调用中不可靠。
如果我们在关键函数中打印cars
,我们可以看到问题:
def myFunc(e):
print(cars)
return cars.count(e)
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi', 'Mitsubishi', 'BMW', 'VW']
cars.sort(key=myFunc)
这输出
[]
[]
[]
[]
[]
[]
[]
所以 cars.count
将 return 0
无论传递什么元素,列表将保留 其原始顺序 .
使用 sorted(...)
而不是 in-place:
def myFunc(e):
return cars.count(e)
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi', 'Mitsubishi', 'BMW', 'VW']
cars = sorted(cars, key=myFunc)
print(cars)
这输出
['BMW', 'VW', 'Mitsubishi', 'Mitsubishi', 'Ford', 'Ford', 'Ford']
作为side-note,在这种情况下你可以直接使用cars.count
,而不用定义包装函数:
cars = sorted(cars, key=cars.count)
这个问题是因为您在修改函数时引用了汽车。
如果您获得副本,则不会发生这种情况:
def myFunc(e):
return cars.count(e)
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi','Mitsubishi', 'BMW', 'VW']
cars2 = cars.copy()
cars2.sort(key=myFunc)
print(cars2)
# ['BMW', 'VW', 'Mitsubishi', 'Mitsubishi', 'Ford', 'Ford', 'Ford']
也就是说,这种方法效率不高,因为您需要为每个元素再次读取整个列表。
改为使用计数器:
from collections import Counter
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi','Mitsubishi', 'BMW', 'VW']
c = Counter(cars)
cars.sort(key=c.get)
print(cars)
# ['BMW', 'VW', 'Mitsubishi', 'Mitsubishi', 'Ford', 'Ford', 'Ford']
# A function that returns the frequency of each value:
def myFunc(e):
return cars.count(e)
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi','Mitsubishi', 'BMW', 'VW']
cars.sort(key=myFunc)
print(cars)
输出:
['Ford', 'Ford', 'Ford', 'Mitsubishi', 'Mitsubishi', 'BMW', 'VW']
我的期望:
['BMW', 'VM', 'Mitsubishi', 'Mitsubishi', 'Ford', 'Ford', 'Ford']
计数:
Ford - 3
Mitsubishi - 2
BMW - 1
VM - 1
它应该按列表中计数的升序排序。
问题是您在关键函数中使用了 cars
,但是 .sort
是 in-place。这导致 cars
在对关键函数的中间调用中不可靠。
如果我们在关键函数中打印cars
,我们可以看到问题:
def myFunc(e):
print(cars)
return cars.count(e)
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi', 'Mitsubishi', 'BMW', 'VW']
cars.sort(key=myFunc)
这输出
[]
[]
[]
[]
[]
[]
[]
所以 cars.count
将 return 0
无论传递什么元素,列表将保留 其原始顺序 .
使用 sorted(...)
而不是 in-place:
def myFunc(e):
return cars.count(e)
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi', 'Mitsubishi', 'BMW', 'VW']
cars = sorted(cars, key=myFunc)
print(cars)
这输出
['BMW', 'VW', 'Mitsubishi', 'Mitsubishi', 'Ford', 'Ford', 'Ford']
作为side-note,在这种情况下你可以直接使用cars.count
,而不用定义包装函数:
cars = sorted(cars, key=cars.count)
这个问题是因为您在修改函数时引用了汽车。
如果您获得副本,则不会发生这种情况:
def myFunc(e):
return cars.count(e)
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi','Mitsubishi', 'BMW', 'VW']
cars2 = cars.copy()
cars2.sort(key=myFunc)
print(cars2)
# ['BMW', 'VW', 'Mitsubishi', 'Mitsubishi', 'Ford', 'Ford', 'Ford']
也就是说,这种方法效率不高,因为您需要为每个元素再次读取整个列表。
改为使用计数器:
from collections import Counter
cars = ['Ford', 'Ford', 'Ford', 'Mitsubishi','Mitsubishi', 'BMW', 'VW']
c = Counter(cars)
cars.sort(key=c.get)
print(cars)
# ['BMW', 'VW', 'Mitsubishi', 'Mitsubishi', 'Ford', 'Ford', 'Ford']