【问题标题】:Python: Sorting y value array according to ascending x arrayPython:根据升序x数组对y值数组进行排序
【发布时间】:2015-11-08 06:15:38
【问题描述】:

如果我有两个数组的形式:

x = [0, 7, 2, 4, 6, 9, 5]

y = [1, 2, 3, 4, 5, 6, 7]

即,我在[0,1][3,2][x_n,y_n] 等处有数据点。我将如何组织y 以获得相应的升序x 值?换句话说,我最终得到x 的升序值:

x = [0, 2, 4, 5, 6, 7, 9]

与其对应的y 值匹配:

y = [1, 3, 4, 7, 5, 2, 6]

我猜我需要将两个数组拼接在一起,然后根据x 进行排序,但我不太确定确切的语法。任何帮助将不胜感激。

【问题讨论】:

    标签: python arrays sorting


    【解决方案1】:

    我会将ziplambda 一起使用:

    In [55]: x = [0, 7, 2, 4, 6, 9, 5]
    
    In [56]: y = [1, 2, 3, 4, 5, 6, 7]
    
    In [57]: L = sorted(zip(x,y), key=operator.itemgetter(0))
    
    In [58]: new_x, new_y = zip(*L)
    
    In [59]: new_x
    Out[59]: (0, 2, 4, 5, 6, 7, 9)
    
    In [60]: new_y
    Out[60]: (1, 3, 4, 7, 5, 2, 6)
    

    别忘了导入operator

    【讨论】:

    • 您不需要指定按第一个元素排序,除非您特别希望在平局的情况下按第二个元素排序。此外,您的代码中没有 lambda
    • 我是这样做的,因为它似乎符合 OP 的要求。但我想不给sorted key 可能会稍微提高运行时效率
    • 当然,它确实合适; OP没有明确说明是否需要/应该打破联系。我只是想我会提到它:)。
    • @Cyphase:明确说明该规范是个好主意。顺便说一句:我真的不确定 OP 想用这个做什么。我猜对最近的一对点应用程序进行某种分而治之?
    • 老兄!这个答案很震撼!
    【解决方案2】:

    你可以在zip他们之后将他们作为元组sorted他们

    >>> sorted((i,j) for i,j in zip(x,y))
    [(0, 1), (2, 3), (4, 4), (5, 7), (6, 5), (7, 2), (9, 6)]
    

    要遍历这些对,您可以执行类似的操作

    sorted_pairs = sorted((i,j) for i,j in zip(x,y))
    for i,j in sorted_pairs:
        # do something with each i and j value, which are x and y respectively
    

    或者你可以直接索引

    sorted_pairs[0][0]  # x of the first tuple
    sorted_pairs[0][1]  # y of the first tuple
    sorted_pairs[3][0]  # x of the fourth tuple... etc
    

    【讨论】:

    • 我现在如何引用 i 值? x[i]?
    • 或者new_x, new_y = zip(*sorted_pairs)。但是,如果这些是单个数据点,则拥有一个元组列表是有意义的。您可以使用namedtuple 来更好地访问它们。或者,如果您只需要迭代它们,请在答案中使用for 循环,并使用更合适的变量名称(我们不知道这些东西是什么,所以我们不能很好地命名它们)。
    • 甚至zip(*sorted(zip(x,y)))
    • @wwii,哦,是的,忘了说:P。对于任何不理解的人,((i, j) for i, j in zip(x, y))zip(x, y) 返回相同的内容,因此您应该直接使用zip(x, y)。 @wwii 的答案中的外部zip 仅当您再次拆分列表时;否则做sorted_pairs = sorted(zip(x, y))
    • @Michael Roberts 如果您需要索引值,请使用enumerate
    【解决方案3】:

    我喜欢其他例子(从他们身上学到了一些东西)。我的回答有点不同:它首先将 x 项转换为 (index, x[index]) 元组,根据元组中的第二项对此类列表进行排序,将索引作为列表取出并使用从y 列表中选择值的索引。

    如果有更多类似y 的列表应根据列表x 中的项目顺序排序,这种方法可能会变得有效。

    精简版

    >>> x = [0, 7, 2, 4, 6, 9, 5]
    >>> y = [1, 2, 3, 4, 5, 6, 7]
    >>> from operator import itemgetter
    >>> pick_0 = itemgetter(0)
    >>> pick_1 = itemgetter(1)
    >>> x_decor = sorted(enumerate(x), key=pick_1)
    >>> x_idxs = map(pick_0, x_decor)
    >>> multi_picker = itemgetter(*x_idxs)
    >>> multi_picker(y)
    (1, 3, 4, 7, 5, 2, 6)
    

    让我解释一下,它是如何工作的,以及为什么它在某些情况下可能是相关的。

    装饰、排序、获取索引、使用它们来挑选结果项

    首先,获取要使用的值:

    >>> x = [0, 7, 2, 4, 6, 9, 5]
    >>> y = [1, 2, 3, 4, 5, 6, 7]
    

    然后使用enumerate用列表x中的项目索引来装饰值:

    >>> x_decor = [(idx, val) for idx, val in enumerate(x)]
    >>> x_decor
    [(0, 0), (1, 7), (2, 2), (3, 4), (4, 6), (5, 9), (6, 5)]
    

    根据值对修饰列表进行排序(现在itm[1] 因为itm[0] 是原始位置索引):

    >>> x_decor.sort(key=lambda itm: itm[1])
    >>> x_decor
    [(0, 0), (2, 2), (3, 4), (6, 5), (4, 6), (1, 7), (5, 9)]
    

    最后只列出与排序的x相关的位置索引:

    >>> x_idxs = [idx for idx, val in x_decor]
    >>> x_idxs
    [0, 2, 3, 6, 4, 1, 5]
    

    现在我们使用x_idxsy 列表中挑选相关项目:

    >>> y_vals = [y[idx] for idx in x_idxs]
    >>> y_vals
    [1, 3, 4, 7, 5, 2, 6]
    

    可以为其他列表重复最后一步(如果我们有的话)。

    使用itemgetter的优化版

    可以使用itemgetter 优化以前的代码(提高速度)。

    itemgetter 能够创建一个函数,允许从特定位置选取值。 itemgetter 还可以创建函数,允许一次从预定义的位置选择多个值。

    >>> from operator import itemgetter
    >>> itemgetter(0)
    <operator.itemgetter at 0x7f8e300afd90>
    >>> pick_0 = itemgetter(0)
    >>> pick_1 = itemgetter(1)
    >>> pick_0_2 = itemgetter(0, 2)
    

    让我们看看,这些函数能为我们做什么:

    >>> pick_0(["a", "b", "c"])
    'a'
    >>> pick_1(["a", "b", "c"])
    'b'
    >>> pick_0_2(["a", "b", "c"])
    ('a', 'c')
    

    让我们像以前一样创建修饰的x,这次使用更短的语法:

    >>> x_decor = sorted(enumerate(x), key=pick_1)
    >>> x_decor
    [(0, 0), (2, 2), (3, 4), (6, 5), (4, 6), (1, 7), (5, 9)]
    

    enumerate(x) 创建修饰列表, sorted 使用 key=pick_1 根据原始 x 列表中的值对其进行排序。

    使用pick_0,我们可以从修饰列表中获取索引列表:

    >>> x_idxs = map(pick_0, x_decor)
    >>> x_idxs
    [0, 2, 3, 6, 4, 1, 5]
    

    这些索引可用于创建multi_picker(类似于上面的pick_0_2):

    >>> multi_picker = itemgetter(*x_idxs)
    >>> multi_picker
    <operator.itemgetter at 0x7f8e300afb10>
    

    并使用multi_picker 从列表y 中获取正确排序的元素:

    >>> y_vals = multi_picker(y)
    >>> y_vals
    (1, 3, 4, 7, 5, 2, 6)
    

    如果我们要根据已排序的x 元素对更多列表进行排序,那么multi_picker 将是现在唯一调用它们的函数。

    【讨论】:

      【解决方案4】:

      嘿,我写了这个函数:

      def sort_bar(bar_list):
          sorted_x = []
          sorted_x.extend(bar_list['x'])
          sorted_x.sort()
          sorted_y = []
          for x in sorted_x:
              sorted_y.append(bar_list['y'][bar_list['x'].index(x)])
          return {"x": sorted_x, "y": sorted_y}
      

      例子:

      unsorted = {
          "x": [5, 9, 2, 3],
          "y": [8, 6, 3, 4]
      }
      sorted = sort_bar(unsorted)
      

      【讨论】:

        猜你喜欢
        • 2015-04-08
        • 2012-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-08
        • 2013-05-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多