python - 如何以完全相同的方式对两个列表(相互引用)进行排序

标签 python list sorting

假设我有两个列表:

list1 = [3, 2, 4, 1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

如果我运行 list1.sort(),它会将其排序到 [1,1,2,3,4] 但有没有办法得到list2 也同步(所以我可以说项目 4 属于 'three')?所以,预期的输出是:

list1 = [1, 1, 2, 3, 4]
list2 = ['one', 'one2', 'two', 'three', 'four']

我的问题是我有一个非常复杂的程序,可以很好地处理列表,但我有点需要开始引用一些数据。我知道这对于字典来说是一个完美的情况,但我试图在处理过程中避免使用字典,因为我确实需要对键值进行排序(如果我必须使用字典,我知道如何使用它们)。

基本上这个程序的本质是,数据以随机顺序出现(如上),我需要对其进行排序,处理然后发送结果(顺序无关紧要,但用户需要知道哪个结果属于哪个键)。我考虑过先将其放入字典中,然后对列表进行排序,但如果不维护顺序,我将无法区分具有相同值的项目(在将结果传达给用户时可能会产生影响)。所以理想情况下,一旦我得到列表,我宁愿想办法将两个列表排序在一起。这可能吗?

最佳答案

解决这个问题的一个经典方法是使用“装饰、排序、取消装饰”的习语,使用python内置的zip函数尤其简单:

>>> list1 = [3,2,4,1, 1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> list1, list2 = zip(*sorted(zip(list1, list2)))
>>> list1
(1, 1, 2, 3, 4)
>>> list2 
('one', 'one2', 'two', 'three', 'four')

这些当然不再是列表,但如果重要的话,这很容易解决:

>>> list1, list2 = (list(t) for t in zip(*sorted(zip(list1, list2))))
>>> list1
[1, 1, 2, 3, 4]
>>> list2
['one', 'one2', 'two', 'three', 'four']

值得注意的是,上面可能会为了简洁而牺牲速度;占用 3 行的就地版本在我的机器上对于小列表来说要快一点:

>>> %timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 3.3 us per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best of 3: 2.84 us per loop

另一方面,对于较大的列表,单行版本可能更快:

>>> %timeit zip(*sorted(zip(list1, list2)))
100 loops, best of 3: 8.09 ms per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100 loops, best of 3: 8.51 ms per loop

正如 Quantum7 指出的那样,JSF's suggestion仍然快一点,但它可能只会快一点,因为 Python 使用 very same DSU idiom internally对于所有基于键的排序。它只是发生在更接近裸机的地方。 (这显示了 zip 例程的优化程度!)

我认为基于 zip 的方法更灵活,可读性更强,所以我更喜欢它。


请注意,当 list1 的元素相等时,这种方法最终会比较 list2 的元素。如果 list2 的元素不支持比较,或者比较时不产生 bool 值(例如,如果 list2 是 NumPy 数组的列表),这将失败, 如果 list2 的元素比较昂贵,最好还是避免比较。

在这种情况下,您可以按照 jfs 的答案中的建议对索引进行排序,或者您可以为排序提供一个避免比较 list2 元素的关键函数:

result1, result2 = zip(*sorted(zip(list1, list2), key=lambda x: x[0]))

此外,当输入为空时,使用 zip(*...) 作为转置会失败。如果您的输入可能为空,您将不得不单独处理这种情况。

关于python - 如何以完全相同的方式对两个列表(相互引用)进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9764298/

相关文章:

python - 如何在python中的一行数据中构造多行日志数据?

Java:列出开始日期和结束日期之间的日期

r - 对两列进行排序,有条件地选择值,然后运行 ​​cumsum frequency

javascript - 根据对象中字段的存在对数组进行排序

java - Collat​​or Locale German - 如何仅在正常字母之后对重音字母进行排序

python - Django:覆盖保存(模型或管理部分)

python - 如何将两个字符串转换为 Python 中的函数名称

python - 如何将文件中的数据写入充满类实例的列表中?

python - 这个生产者消费者代码有什么问题?

java - 将逗号与列表分开并在Java中显示在单行中