【问题标题】:Sort 2 list linked to each other对彼此链接的 2 个列表进行排序
【发布时间】:2019-03-05 15:42:09
【问题描述】:

我陷入了一个问题,我想不出任何有效的方法来做到这一点。问题如下:

我有 2 个列表,每个列表都有 n10^3

v = [v_1, v_2, ..., v_n]
w = [w_1, w_2, ..., w_n]

在下面的例子中n = 3

v = [60, 100 , 120] 
w = [20, 50, 30]

我需要根据以下等式的降序对两个列表进行排序:v_i/w_i

所以在这种情况下我会得到:

v_1/w_1 = 3
v_2/w_2 = 2
v_3/w_3 = 4

之后我需要按降序对两个列表(相互依赖)进行排序,我会得到以下结果。

v_new = [120, 60, 100]
w_new = [30, 20, 50]

我知道 sorted(zip(X,Y) 有一种方法,但这样做会改变我的元组列表,我需要它作为列表。有什么建议吗?

【问题讨论】:

  • 您想进行就地排序还是创建一个新的 v 和 w 可以吗?

标签: python python-3.x list sorting


【解决方案1】:

Python 的排序函数可以带一个键,您可以使用 lambda 函数来定义要排序的键。在这种情况下,我建议对索引进行排序,然后将顺序应用于vw。例如:

v = [60, 100 , 120] 
w = [20, 50, 30]
order = sorted(range(len(v)), key=lambda i: v[i] / w[i], reverse=True)

v_new = [v[i] for i in order]
w_new = [w[i] for i in order]

【讨论】:

  • 我想我忘了提到这些列表是相互依赖的。因此,首先对列表进行排序会弄乱彼此的依赖关系。
  • @RobertKodra 我想你误解了我的回答。 vw 从不排序。我们发现排序需要对v_i / w_i 进行排序,然后使用该排序创建新列表。
  • 对不起。确实你是对的。这真的很好用。谢谢。
【解决方案2】:

使用sortedkey 根据条件排序,然后给出一个元组列表,我们使用zip 将它们分成两个列表:

v = [60, 100 , 120] 
w = [20, 50, 30]

v, w = map(list, zip(*sorted(zip(v, w), key=lambda x: - x[0] / x[1])))

print(v)  # [120, 60, 100]
print(w)  # [30, 20, 50]

或者,您可以在相同的代码中使用reverse=True,例如:

v = [60, 100 , 120] 
w = [20, 50, 30]

v, w = map(list, zip(*sorted(zip(v, w), key=lambda x: x[0] / x[1], reverse=True)))

这也产生了想要的东西。

【讨论】:

  • 这将起作用,但请注意 zip 只能在最小列表的长度内起作用。 - 可能也想给itertools.zip_longest 看看。
  • @JulianCamilleri,OP 明确提到两个列表的长度相同。
  • 我看到了老兄,只是把它放在那里以防其他人看到这个帖子。
  • 使用 reverse=true 而不是否定 (-) 会更好,更符合 Python 风格
  • @RobertKodra zip 返回一个迭代器,它不会占用太多 RAM。这个答案比 Bi Rico 的答案使用了更多的 RAM。 Austin's 产生一个临时排序的元组列表,Bi Rico's 产生一个整数索引列表(你应该在它完成它的工作后删除它,尽管如果这个代码在一个函数中,当函数返回时会自动发生)。包含 2 个项目的元组对象相当小,它使用的 RAM 是小型 int 对象的两倍多一点(32 字节对 14 字节)。每个元组的内容将只是指向来自vw 的数字对象的指针。
【解决方案3】:

你可以使用熊猫:

import pandas as pd
v = [60, 100, 120]
w = [20, 50, 30]
vv = pd.Series(v)
ww = pd.Series(w)
new_index = list((vv/ww).sort_values(ascending=False).index.values)
v_new = list(vv.reindex(new_index))
w_new = list(ww.reindex(new_index))
print(v_new)
print(w_new)

输出:

[120, 60, 100]

[30、20、50]

【讨论】:

    【解决方案4】:

    这个问题没有提到 numpy,但我想我会使用 numpy 添加一个答案,因为它可以很好地处理这种事情。 Numpy 有一个 argsort,可用于将任何排序的排序应用于其他数组,例如:

    import numpy as np
    
    v = np.array([60, 100 , 120])
    w = np.array([20, 50, 30])
    
    order = np.argsort(v / w)[::-1]
    v_new = v[order]
    w_new = w[order]
    

    argsort 没有reverse 参数,但我们总是可以使用[::-1] 反转输出。

    【讨论】:

      猜你喜欢
      • 2021-09-10
      • 2012-11-07
      • 1970-01-01
      • 1970-01-01
      • 2013-02-22
      • 2013-07-29
      • 2015-06-30
      • 1970-01-01
      • 2012-04-30
      相关资源
      最近更新 更多