python - 使用 zip() 对元组列表进行排序时,有时不支持“<”

标签 python python-3.x sorting

我想根据第二个列表对列表进行排序,如 this堆栈溢出帖子。 就我而言,我的代码试图对 Chromo 进行排序对象对应的 fitness_weights ,所以我尝试了链接帖子中的解决方案:

def foobar():
    ...
    chromolist = [x for _, x in sorted(zip(fitness_weights, chromolist))]
    ...

报错:

TypeError: '<' not supported between instances of 'Chromo' and 'Chromo'

为了调试我试过:

def foobar():
    ...
    try:
        chromolist = [x for _, x in sorted(zip(fitness_weights, chromolist))]
    except Exception as e:
        print(fitness_weights)
        print(chromolist)
        print([i for i in zip(fitness_weights, chromolist)])
        raise e
    print('works fine')
    ...

输出:

works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
works fine
[2630793242, 2662598634, 1204127226, 1218205610, 1224753838, 1212750850, 
1212293610, 1221507266, 1269226518, 1363578674, 1209661338, 2674408754, 
1179213986, 1209887778, 2281636710, 1906925334, 1156258126, 1287144442, 
1218205610, 1256241498, 2926198286, 1533442630, 1587421406, 2685579290, 
1203563674, 1205066274, 1181576990, 1188462746, 1127834446, 2295554650, 
1216261042, 1193222146, 1191591394, 1206052810, 1206800842, 1213410890, 
1202786310, 1230097202, 1277296358, 1218982810]

[Chromo Object, Chromo Object, Chromo Object, Chromo Object, Chromo Object, 
Chromo Object, Chromo Object, Chromo Object, Chromo Object, Chromo Object, 
Chromo Object, Chromo Object, Chromo Object, Chromo Object, Chromo Object, 
Chromo Object, Chromo Object, Chromo Object, Chromo Object, Chromo Object, 
Chromo Object, Chromo Object, Chromo Object, Chromo Object, Chromo Object, 
Chromo Object, Chromo Object, Chromo Object, Chromo Object, Chromo Object, 
Chromo Object, Chromo Object, Chromo Object, Chromo Object, Chromo Object, 
Chromo Object, Chromo Object, Chromo Object, Chromo Object, Chromo Object]

[(2630793242, Chromo Object), (2662598634, Chromo Object), 
(1204127226, Chromo Object), (1218205610, Chromo Object),
(1224753838, Chromo Object), (1212750850, Chromo Object),
(1212293610, Chrom Object), (1221507266, Chromo Object), 
(1269226518, Chromo Object), (1363578674, Chromo Object), 
(1209661338, Chromo  Object), (2674408754, Chromo Object),
(1179213986, Chromo Object), (1209887778, Chromo Object), 
(2281636710, Chromo Object), (1906925334, Chromo Object), 
(1156258126, Chromo Object), (1287144442, Chromo Object), 
(1218205610, Chromo  Object), (1256241498, Chromo Object),
(2926198286, Chromo Object), (1533442630, Chromo Object), 
(1587421406, Chromo Object), (2685579290, Chromo Object), 
(1203563674, Chromo Object), (1205066274, Chromo Object), 
(1181576990, Chromo  Object), (1188462746, Chromo Object), 
(1127834446, Chromo Object), (2295554650, Chromo Object),
(1216261042, Chromo Object), (1193222146, Chromo Object), 
(1191591394, Chromo Object), (1206052810, Chromo Object), 
(1206800842, Chromo  Object), (1213410890, Chromo Object), 
(1202786310, Chromo Object), (1230097202, Chromo Object), 
(1277296358, Chromo Object), (1218982810, Chromo Object)]

这是令人困惑的,因为:

  • 所有数据类型都正确
  • 该功能正确运行了 22 次

我该如何解决这个问题?

最佳答案

当您有两个具有相等权重的 (weight, chromo) 对时会发生错误,此时 Python 会尝试比较 chromo 值:

>>> class Chromo:
...     pass
...
>>> chromolist = [Chromo(), Chromo()]
>>> fitness_weights = [42, 42]
>>> sorted(zip(fitness_weights, chromolist))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'Chromo' and 'Chromo'

您可以通过使用仅提取权重的自定义排序键或添加对排序序列中的每个值都是唯一的决胜局(例如计数器)来避免此问题:

from itertools import count

chromolist = [x for *_, x in sorted(zip(fitness_weights, count(), chromolist))]

计数器只是为了确保 Python 永远不会查看 Chromo 实例,因为现在每个元素都是一个 (weight, unique_integer, Chromo) 元组:

>>> from itertools import count
>>> sorted(zip(fitness_weights, count(), chromolist))
[(42, 0, <__main__.Chromo object at 0x1038cfa00>), (42, 1, <__main__.Chromo object at 0x103a396d0>)]

排序键只是一个生成要比较的值的函数,您可以使用 lambda (lambda t: t[0]) 或 operator.itemgetter() object :

from operator import itemgetter

chromolist = [x for _, x in sorted(zip(fitness_weights, chromolist), key=itemgetter(0))]

key 函数需要单独传递输入列表,因此速度稍慢,如这个具有 200 个输入的简单时间试验所示:

>>> from timeit import timeit
>>> fw = fitness_weights * 100
>>> cl = chromolist * 100
>>> timeit('sorted(zip(fw, count(), cl))', globals=globals(), number=100000)
1.4618491119981627
>>> timeit('sorted(zip(fw, cl), key=itemgetter(0))', globals=globals(), number=100000)
1.6409574589997646

关于python - 使用 zip() 对元组列表进行排序时,有时不支持“<”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61646046/

相关文章:

arrays - 关于数组的问题之间的区别

Jquery 到 Python/Django 查询字典

python - Pandas 多索引嵌套排序和百分比

python - 如何使用Python从网页的检查元素中获取数据

python - 使用 Github API 获取所有存储库的最后一次提交

python-3.x - 输出文件为空,在Docker容器中的ubuntu16.04中未进行任何编码(检查-ss/-t/-frames参数(如果使用))

c++ - 如何将 C++ STL vector 迭代器转换为 vector 反向迭代器?

MySQL 按 DESC 顺序对三列进行排序

python - [b, c][a < b < c] +'000' [a < c :] expression do? 是什么

python - google.protobuf.message.DecodeError : Wrong wire type in tag Error in Protocol Buffer