关于python:根据另一个列表中的值对列表进行排序?

Sorting list based on values from another list?

我有一个这样的字符串列表:

1
2
X = ["a","b","c","d","e","f","g","h","i"]
Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

使用y中的值对x进行排序以获得以下输出的最短方法是什么?

1
["a","d","h","b","c","e","i","f","g"]

具有相同"键"的元素的顺序无关紧要。我可以使用for构造,但是我很好奇是否有一个更短的方法。有什么建议吗?


短码

1
[x for _,x in sorted(zip(Y,X))]

Example:

ZZU1

一般性讲话

1
[x for _, x in sorted(zip(Y,X), key=lambda pair: pair[0])]

解释:

  • 第二次世界大战
  • zip为基础,利用sorted()创建一个新的list
  • 使用一个列表解读从每一对中提取第一个元素,拉链list
  • 关于如何使用key参数和sorted函数的更多信息,请看这个。


    把两张名单合起来,抽出来,然后拿走你想要的部分:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> yx = zip(Y, X)
    >>> yx
    [(0, 'a'), (1, 'b'), (1, 'c'), (0, 'd'), (1, 'e'), (2, 'f'), (2, 'g'), (0, 'h'), (1, 'i')]
    >>> yx.sort()
    >>> yx
    [(0, 'a'), (0, 'd'), (0, 'h'), (1, 'b'), (1, 'c'), (1, 'e'), (1, 'i'), (2, 'f'), (2, 'g')]
    >>> x_sorted = [x for y, x in yx]
    >>> x_sorted
    ['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

    Combinee these together to get:

    1
    [x for y, x in sorted(zip(Y, X))]


    此外,如果你不考虑使用numpy arrays(或事实上,already are dealing with numpy arrays…),这是另一个很好的解决办法:

    1
    2
    3
    4
    5
    6
    7
    8
    people = ['Jim', 'Pam', 'Micheal', 'Dwight']
    ages = [27, 25, 4, 9]

    import numpy
    people = numpy.array(people)
    ages = numpy.array(ages)
    inds = ages.argsort()
    sortedPeople = people[inds]

    我发现了http://scienceoss.com/sort-one-list-by-another-list/。


    最明显的解决办法是用key关键词ARG。

    1
    2
    3
    4
    5
    6
    >>> X = ["a","b","c","d","e","f","g","h","i"]
    >>> Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]
    >>> keydict = dict(zip(X, Y))
    >>> X.sort(key=keydict.get)
    >>> X
    ['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

    注:如果你在乎:

    1
    >>> X.sort(key=dict(zip(X, Y)).get)


    我喜欢有各种线索的清单。这样,我就可以把任何列表按原始列表顺序排列。一旦你有了一份各类线索的清单,一份简单的清单会做作弊:

    1
    2
    3
    4
    5
    6
    7
    8
        X = ["a","b","c","d","e","f","g","h","i"]
        Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

        sorted_y_idx_list = sorted(range(len(Y)),key=lambda x:Y[x])
        Xs = [X[i] for i in sorted_y_idx_list ]

        print("Xs:", Xs )
        # prints: Xs: ["a","d","h","b","c","e","i","f","g"]

    注:各种索引列表也可以使用Numpy Argorte()。


    另一种选择,组合几种答案。

    1
    zip(*sorted(zip(Y,X)))[1]

    In order to work for Python3:

    1
    list(zip(*sorted(zip(B,A))))[1]


    事实上,我来到这里,想通过一份清单,列出价值匹配的地方。

    1
    2
    3
    4
    list_a = ['foo', 'bar', 'baz']
    list_b = ['baz', 'bar', 'foo']
    sorted(list_b, key=lambda x: list_a.index(x))
    # ['foo', 'bar', 'baz']


    有一个工具可用于平行输出:

    1
    2
    3
    4
    from more_itertools import sort_together

    sort_together([Y, X])[1]
    # ('a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g')

    拉链,从第二根柱抽出,返回第一根柱。

    1
    zip(*sorted(zip(X,Y), key=operator.itemgetter(1)))[0]


    一条快线

    1
    2
    list_a = [5,4,3,2,1]
    list_b = [1,1.5,1.75,2,3,3.5,3.75,4,5]

    说你想列一张比赛名单

    1
    orderedList =  sorted(list_a, key=lambda x: list_b.index(x))

    这是当需要订购一份小清单,以便在广告中增值时的帮助。假设广告名单包含小名单中的所有价值,就可以做到这一点。


    我创建了一个更广泛的功能,比基于另一个单元的两个列表更有意义,受@whatang's answer的启发。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def parallel_sort(*lists):
       """
        Sorts the given lists, based on the first one.
        :param lists: lists to be sorted

        :return: a tuple containing the sorted lists
       """


        # Create the initially empty lists to later store the sorted items
        sorted_lists = tuple([] for _ in range(len(lists)))

        # Unpack the lists, sort them, zip them and iterate over them
        for t in sorted(zip(*lists)):
            # list items are now sorted based on the first list
            for i, item in enumerate(t):    # for each item...
                sorted_lists[i].append(item)  # ...store it in the appropriate list

        return sorted_lists


    你可以创建一个pandas Series,使用原始列表作为data和其他列表作为index,然后按索引排列:

    1
    2
    import pandas as pd
    pd.Series(data=X,index=Y).sort_index().tolist()

    输出

    1
    ['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

    如果你想同时得到各种名单(Python3),这就是你的答案。

    1
    2
    3
    4
    5
    6
    7
    X = ["a","b","c","d","e","f","g","h","i"]
    Y = [ 0,   1,   1,    0,   1,   2,   2,   0,   1]

    Zx, Zy = zip(*[(x, y) for x, y in sorted(zip(Y, X))])

    print(list(Zx))  # [0, 0, 0, 1, 1, 1, 1, 2, 2]
    print(list(Zy))  # ['a', 'd', 'h', 'b', 'c', 'e', 'i', 'f', 'g']

    记住ZX和Zy是双胞胎。如果有更好的方法去做,我也很想知道。

    警告:如果你用空隙列表运行它。


    1
    2
    3
    4
    5
    list1 = ['a','b','c','d','e','f','g','h','i']
    list2 = [0,1,1,0,1,2,2,0,1]

    output=[]
    cur_loclist = []

    获得list2的唯一值

    1
    list_set = set(list2)

    在EDOCX1&13中找到索引的位置

    1
    list_str = ''.join(str(s) for s in list2)

    指数在EDOCX1&13中的位置

    [0、3、7、1、2、4、8、5、6]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for i in list_set:
    cur_loc = list_str.find(str(i))

    while cur_loc >= 0:
        cur_loclist.append(cur_loc)
        cur_loc = list_str.find(str(i),cur_loc+1)

    print(cur_loclist)

    for i in range(0,len(cur_loclist)):
    output.append(list1[cur_loclist[i]])
    print(output)