【问题标题】:Sort one list to to make two lists have correct order correspondence对一个列表进行排序以使两个列表具有正确的顺序对应关系
【发布时间】:2019-02-19 15:35:23
【问题描述】:

我有两个列表,例如

coords = [2, 0, 1, 4, 3]
value = [1, 9, 3, 3, 0]

其中第一个是一系列坐标,第二个是与坐标对应的一系列值,例如坐标'2' 对应于值'1',坐标'0' 给出值'9'

现在,我想对coords进行排序但是保持value的顺序不变,这样最小的coords元素对应于value中的最小元素,以此类推在。期望的输出是:

coords_new = [1, 4, 2, 3, 0]
value = [1, 9, 3, 3, 0] # unchanged

在哪里'0' -> '0', '1' -> '1', '2' -> '3', '3' -> '3', '4' -> '9'。 有什么想法吗?您可以返回 coords_new,或将 coords 重新排序的索引作为答案。

编辑: 如果可能的话,我希望我们可以返回对原始coords 重新排序的索引,即返回idx 使得coords[idx] = coords_new

非常感谢!

志豪

【问题讨论】:

  • 只需使用np.argsort 生成排序索引。
  • 好吧,我不认为 np.argsort 可以直接获得所需的输出......有什么想法吗?
  • 就我而言,坐标应该是唯一的。但是如果你能得到一个一般情况的解决方案那就更好了。

标签: python list sorting numpy dictionary


【解决方案1】:

这里是使用 argsort 的一个半解决方案。 kind='mergesort' kwd 参数仅在您需要稳定排序时才需要。在您的示例中,不稳定的排序也可能产生coords_new == [1, 4, 3, 2, 0]。如果这不是问题,您可以省略 kwd 参数并允许 numpy 使用更快的排序算法。

import numpy as np

coords = [2, 0, 1, 4, 3]
value = [1, 9, 3, 3, 0]

coords, value = map(np.asanyarray, (coords, value))

vidx = value.argsort(kind='mergesort') # mergesort is stable, i.e. it  
                                       # preserves the order of equal elements

# direct method:
coords_new = np.empty_like(coords)
coords_new[vidx] = np.sort(coords)

# method yielding idx
idx = np.empty_like(vidx)
idx[vidx] = coords.argsort(kind='mergesort') 

第二种方法产生idx,这样coords_new == coords[idx]

【讨论】:

    【解决方案2】:

    我假设你想要一个 numpy 的答案,因为你已经标记了 numpy:

    >>> x = np.argsort(value)
    >>> x[x]
    array([1, 4, 2, 3, 0])
    

    【讨论】:

    • 感谢您的回答。看起来不错。但是有没有办法不返回 coords_new 而是直接返回 idx 使得 coords[idx] = coords_new?
    • 是的,但也许您应该编辑问题,包括预期的结果,以便更清楚地区别。使用无论哪种方式看起来都相同的示例数据是不好的,这只会造成不必要的混乱。
    • 在您编辑完问题后,我将发布idx的解决方案。
    【解决方案3】:

    另一种方法是先创建对象之间的映射,然后将此映射与索引结合使用:

    coords = [2, 0, 1, 4, 3]
    value = [1, 9, 3, 3, 0]
    
    table = {k: v for k, v in zip(sorted(coords), sorted(value))}
    print(table)
    print(sorted(coords, key=lambda e: value.index(table[e])))
    

    输出

    {0: 0, 1: 1, 2: 3, 3: 3, 4: 9}
    [1, 4, 2, 3, 0]
    

    注意

    此方法假定coords 仅包含唯一值。对于一般情况,您可以生成映射的对 (c, v) 按值中 v 的索引值排序:

    pairs = [(k, v) for k, v in zip(sorted(coords), sorted(value))]
    result = [k for k, _ in sorted(pairs, key=lambda e: value.index(e[1]))]
    
    print(result)
    

    输出

    [1, 4, 2, 3, 0]
    

    【讨论】:

    • 感谢您的回答!有没有办法让索引idxcoords 重新排序为新索引?即我们可以从coords[idx] 得到coords_new
    • 您可以在新列表中使用索引功能。
    • 查看Rearrange columns of numpy 2D array 的排列位。
    猜你喜欢
    • 2012-08-17
    • 2017-07-15
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    • 2019-09-24
    相关资源
    最近更新 更多