Python - 如何根据另一个列表列表的最后一个元素对列表列表进行排序?

Python - How to sort a list of lists by last element of another list of lists?

我有一个包含 n 个值向量的列表和一个包含 n 个时间向量的列表。我想根据每个值向量的最后一个元素对时间向量进行排序。我想在每个时间向量上附加相应值向量的最后一个元素,然后使用

time_vector.sort(key=lambda x: x[-1]) #or
time_vector.sort(key=itemgetter(-1))

最后弹出每个时间向量的最后一个元素。 但是,我认为必须有一种更简单的方法来做到这一点。我无法在排序和排序的 Python 参考中找到任何关于此问题的示例。

使用 Alex-Martelli 提出的解决方案扩展了问题。因为我必须重新排序值向量 v_v 和时间向量 t_v,Alex 提供了一站式解决方案

(v_v, t_v) = zip(*sorted (zip(v_v, t_v),key=lambda v: v[0][-1]))

我不明白解压缩是如何工作的,但我只是从 Python 的文档中复制了它,并且它可以工作。另一个问题是为什么使用 itemgetter() 而不是 lambda 这不起作用,以及为什么它不适用于 vector.sort() 方法而不是使用函数 sorted()

我用来测试上面的数值例子是

v_v = [[1, 2], [2, 3], [3, 1], [5, 3, 4]]
t_v = [[1, 1], [5, 6], [9, 8], [3, 10, 1]]

产生

的排序结果
v_v = ([3, 1], [1, 2], [2, 3], [5, 3, 4])
t_v = ([9, 8], [1, 1], [5, 6], [3, 10, 1])

因为这两个向量是——而且显然需要保留! -- 分开,这是好的旧 DSU 的情况 -- 装饰、分类、取消装饰。

result = [t for v, t in
          sorted(zip(value_vector, time_vector), key=lambda vt: vt[0][-1])]

添加 key= arg 几乎消除了在大多数情况下理解 DSU 的需要——它为您做了装饰(只要它只是每个项目的函数)和排序后也未修饰。

但是在这里,排序键 而不是 只是项目的函数 -- 它是项目在 position 中的函数列表,用于索引单独的并行列表(Python 中非常不寻常的数据排列)。然而,您想对 进行排序(即使它们本身与所需的顺序完全无关!)——这就是困难的症结所在。

或者,考虑对位置进行排序,然后使用它们对时间重新排序。这可能感觉不那么奇怪:-)。它可以折叠成一个语句,但当呈现为两个时可能会更清楚:

idx_val = sorted(enumerate(value_vector), key=lambda i, v: v[-1])
result = [times_vector[i] for i, _ in idx_val]

我认为这可能更清楚,因为 idx_val(正确排序的 (index, value) 对列表,我们实际上并不进一步关心 value 但需要它进行排序) 不是 "glued on" 到时代然后必须再次扯掉 - 而我们只是在列表理解中使用索引。命名和分成两步有帮助。

(但当然,如果您是 "one statement to rule them all" 的狂热爱好者,您可以将 sorted 调用替换为 listcomp 中的 idx_val 名称,然后返回到单个语句-- 根本没有真正的优势,但是,对于错误的人来说,"cooler":-)]

补充:DSU 的另一种伪装是 OrderedDict —— 只是 "undecorate" 的一种不同方式,真的。但是有一位评论者提到了它,所以它就在这里——你可以判断它是否提供任何价值。

import collections
od = collections.OrderedDict(
    sorted(zip(value_vector, time_vector),
           key=lambda v, t: v[-1]))
result = list(od.values())

我实际上认为通过在 dict 子类的 keys/values 游戏中隐藏未修饰,它使事情变得更加模糊。但是,de gustibus...