我想按照它们与原点(0,0)的距离按升序对2D坐标系中的点进行排序。我找到this并尝试了一些东西,但仍然无法得到理想的结果。
这是我的代码:
from functools import cmp_to_key
def my_comp(point1, point2):
return point1[0]*point1[0] + point1[1]*point1[1] < point2[0]*point2[0] + point2[1]*point2[1]
points = [ [3.1, 4.1], [0.9, 0.8], [1.0, 1.0] ]
sorted(points, key=cmp_to_key(my_comp))
print(points)
结果:
[[3.1, 4.1], [0.9, 0.8], [1.0, 1.0]]
预期:
[[0.9, 0.8], [1.0, 1.0], [3.1, 4.1]]
答案 0 :(得分:8)
1)你的my_cmp()
函数应该返回三个值中的一个(+, - 或0,具体取决于比较),但你只返回两个(True和False)。
2)你从sorted()
获得了返回值。 sorted()
不会修改其参数,它会返回它的排序副本。
3)不要使用cmp功能。它们很难描述,很难实现。而是使用关键功能。
怎么样:
def my_key(point1):
return point1[0]*point1[0] + point1[1]*point1[1]
points = [ [3.1, 4.1], [0.9, 0.8], [1.0, 1.0] ]
points = sorted(points, key=my_key)
print(points)
assert points == [ [0.9, 0.8], [1.0, 1.0], [3.1, 4.1] ]
答案 1 :(得分:4)
这样做你想要的吗?
sorted_points = sorted(points, key=lambda p: p[0]*p[0] + p[1]*p[1])
在原始代码中需要注意的另一件事是,排序不会对列表进行排序,它会创建一个已排序的新列表。所以当你这样做时
points = [3,2,1]
sorted(points)
print(points)
您的代码似乎没有排序,因为您打印的是原始列表而不是新创建的排序列表。你可以这样进行排序。
points = [3,2,1]
points.sort()
print(points)
答案 2 :(得分:1)
看起来你正在经历一些额外的箍。您的数量已经是完美的关键。您可以定义一个比较器来重新计算并比较每对对象的两个量,然后将该比较器转换回一个键,而不仅仅使用它。
这似乎非常低效。为什么不直接定义一个简单的键函数并直接使用它?
def distance_from_origin_squared(point):
return point[0]**2 + point[1]**2
points = sorted(points, key=distance_from_origin_squared)
请记住,sorted
不会就地运行,因此您必须将其存放在某处。如果罚款,请更换原始名称。如果您想要就地排序,请改用list.sort
:
points.sort(key=distance_from_origin_squared)
从实用的角度来看,键与比较器相比具有许多优点。首先,每个元素只需调用一次键函数,而比较器调用O(nlog(n))
次。当然,密钥比较O(nlog(n))
次,但比较通常要简单得多,因为感兴趣的值是预先计算的。
来自C(在我的情况下)的主要困难是掌握了键不必是单个整数的想法,如示例中通常所示。键可以是任何类型,明确定义<
(或>
)运算符。字符串,列表和元组的字典比较使得将复杂的链式比较器很容易地煮成一个只是一个短序列值的键。
答案 3 :(得分:-1)
您对cmp
和key
参数感到困惑。 cmp
函数接受两个参数并返回-1
,0
或1
。 key
函数返回将用于对列表进行排序的代理值。 {3}中cmp
的{{1}}作为参数被移除。