基于另一个列表的值排序列表?

时间:2022-09-28 18:06:42

I have a list of strings like this:

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

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

What is the shortest way of sorting X using values from Y to get the following output?

用Y的值排序X以得到以下输出的最短方法是什么?

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

The order of the elements having the same "key" does not matter. I can resort to the use of for constructs but I am curious if there is a shorter way. Any suggestions?

具有相同“键”的元素的顺序并不重要。我可以使用for结构,但是我很好奇是否有更短的方法。有什么建议吗?

13 个解决方案

#1


257  

Shortest Code

最短的代码

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

Example:

例子:

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

Z = [x for _,x in sorted(zip(Y,X))]
print(Z)  # ["a", "d", "h", "b", "c", "e", "i", "f", "g"]

Generally Speaking

一般来说

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

Explained:

解释道:

  1. zip the two lists.
  2. 压缩这两个列表。
  3. create a new, sorted list based on the zip using sorted().
  4. 根据使用排序()的zip创建一个新的排序列表。
  5. using a list comprehension extract the first elements of each pair from the sorted, zipped list.
  6. 使用列表理解从排序的压缩列表中提取每对的第一个元素。

For more information on how to set\use the key parameter as well as the sorted function in general, take a look at this.

有关如何设置\使用键参数和排序函数的详细信息,请参阅本文。


#2


84  

Zip the two lists together, sort it, then take the parts you want:

把两个列表压缩在一起,分类,然后取你想要的部分:

>>> 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']

Combine these together to get:

把这些结合起来得到:

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

#3


48  

Also, if you don't mind using numpy arrays (or in fact already are dealing with numpy arrays...), here is another nice solution:

另外,如果您不介意使用numpy数组(或者实际上已经在处理numpy数组…),这里还有一个不错的解决方案:

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]

I found it here: http://scienceoss.com/sort-one-list-by-another-list/

我在这里找到了:http://scienceoss.com/sort-one-list-by- other-list/

#4


27  

The most obvious solution to me is to use the key keyword arg.

对我来说最明显的解决方案是使用关键字arg。

>>> 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']

Note that you can shorten this to a one-liner if you care to:

注意,如果你想要:

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

#5


9  

I like having a list of sorted indices. That way, I can sort any list in the same order as the source list. Once you have a list of sorted indices, a simple list comprehension will do the trick:

我喜欢有一个排序索引的列表。这样,我就可以按照与源列表相同的顺序对任何列表进行排序。一旦你有了一个排序索引的列表,一个简单的列表理解就可以做到:

    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"]

Note that the sorted index list can also be gotten using numpy argsort().

注意,还可以使用numpy argsort()来获得排序的索引列表。

#6


5  

Another alternative, combining several of the answers.

另一种选择,结合几个答案。

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

In order to work for python3:

为了让python3运行:

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

#7


4  

zip, sort by the second column, return the first column.

zip,按第二列排序,返回第一列。

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

#8


3  

more_itertools has a tool for sorting iterables in parallel:

more_itertools有一个并行排序迭代的工具:

from more_itertools import sort_together

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

#9


1  

A quick one-liner.

一个快速的一行程序。

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

Say you want list a to match list b.

假设你想要列表a与列表b匹配。

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

This is helpful when needing to order a smaller list to values in larger. Assuming that the larger list contains all values in the smaller list, it can be done.

当需要将较小的列表订购到较大的值时,这是很有用的。假设大列表包含小列表中的所有值,那么可以这样做。

#10


0  

You can create a pandas Series, using the primary list as data and the other list as index, and then just sort by the index:

您可以创建一个熊猫系列,使用主列表作为数据,另一个列表作为索引,然后按索引排序:

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

output:

输出:

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

#11


0  

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

list1 =[a,b,c,d,e,f,g,h,'我']用于=[0,1,1,0,1,2,2,0,1]

output=[] cur_loclist = []

输出=[]cur_loclist =[]

to get unique values present in list2

获取列表2中唯一的值

list_set = set(list2)

to find the loc of the index in list2

在清单2中找到索引的loc

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

location of index in list2 is tracked using cur_loclist [0, 3, 7, 1, 2, 4, 8, 5, 6]

list2中的索引位置使用cur_loclist跟踪[0,3,7,1,2,4,8,5,6]

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)

#12


0  

Here is Whatangs answer if you want to get both sorted lists (python3).

如果您想要得到两个已排序的列表(python3),那么这里是Whatangs的答案。

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']

Just remember Zx and Zy are tuples. I am also wandering if there is a better way to do that.

记住Zx和Zy是元组。如果有更好的办法,我也在流浪。

Warning: If you run it with empty lists it crashes.

警告:如果你用空列表运行它,它会崩溃。

#13


0  

I have created a more general function, that sorts more than two lists based on another one, inspired by @Whatang's answer.

我创建了一个更通用的函数,根据@Whatang的答案,根据另一个列表对多个列表进行排序。

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

#1


257  

Shortest Code

最短的代码

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

Example:

例子:

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

Z = [x for _,x in sorted(zip(Y,X))]
print(Z)  # ["a", "d", "h", "b", "c", "e", "i", "f", "g"]

Generally Speaking

一般来说

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

Explained:

解释道:

  1. zip the two lists.
  2. 压缩这两个列表。
  3. create a new, sorted list based on the zip using sorted().
  4. 根据使用排序()的zip创建一个新的排序列表。
  5. using a list comprehension extract the first elements of each pair from the sorted, zipped list.
  6. 使用列表理解从排序的压缩列表中提取每对的第一个元素。

For more information on how to set\use the key parameter as well as the sorted function in general, take a look at this.

有关如何设置\使用键参数和排序函数的详细信息,请参阅本文。


#2


84  

Zip the two lists together, sort it, then take the parts you want:

把两个列表压缩在一起,分类,然后取你想要的部分:

>>> 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']

Combine these together to get:

把这些结合起来得到:

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

#3


48  

Also, if you don't mind using numpy arrays (or in fact already are dealing with numpy arrays...), here is another nice solution:

另外,如果您不介意使用numpy数组(或者实际上已经在处理numpy数组…),这里还有一个不错的解决方案:

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]

I found it here: http://scienceoss.com/sort-one-list-by-another-list/

我在这里找到了:http://scienceoss.com/sort-one-list-by- other-list/

#4


27  

The most obvious solution to me is to use the key keyword arg.

对我来说最明显的解决方案是使用关键字arg。

>>> 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']

Note that you can shorten this to a one-liner if you care to:

注意,如果你想要:

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

#5


9  

I like having a list of sorted indices. That way, I can sort any list in the same order as the source list. Once you have a list of sorted indices, a simple list comprehension will do the trick:

我喜欢有一个排序索引的列表。这样,我就可以按照与源列表相同的顺序对任何列表进行排序。一旦你有了一个排序索引的列表,一个简单的列表理解就可以做到:

    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"]

Note that the sorted index list can also be gotten using numpy argsort().

注意,还可以使用numpy argsort()来获得排序的索引列表。

#6


5  

Another alternative, combining several of the answers.

另一种选择,结合几个答案。

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

In order to work for python3:

为了让python3运行:

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

#7


4  

zip, sort by the second column, return the first column.

zip,按第二列排序,返回第一列。

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

#8


3  

more_itertools has a tool for sorting iterables in parallel:

more_itertools有一个并行排序迭代的工具:

from more_itertools import sort_together

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

#9


1  

A quick one-liner.

一个快速的一行程序。

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

Say you want list a to match list b.

假设你想要列表a与列表b匹配。

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

This is helpful when needing to order a smaller list to values in larger. Assuming that the larger list contains all values in the smaller list, it can be done.

当需要将较小的列表订购到较大的值时,这是很有用的。假设大列表包含小列表中的所有值,那么可以这样做。

#10


0  

You can create a pandas Series, using the primary list as data and the other list as index, and then just sort by the index:

您可以创建一个熊猫系列,使用主列表作为数据,另一个列表作为索引,然后按索引排序:

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

output:

输出:

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

#11


0  

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

list1 =[a,b,c,d,e,f,g,h,'我']用于=[0,1,1,0,1,2,2,0,1]

output=[] cur_loclist = []

输出=[]cur_loclist =[]

to get unique values present in list2

获取列表2中唯一的值

list_set = set(list2)

to find the loc of the index in list2

在清单2中找到索引的loc

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

location of index in list2 is tracked using cur_loclist [0, 3, 7, 1, 2, 4, 8, 5, 6]

list2中的索引位置使用cur_loclist跟踪[0,3,7,1,2,4,8,5,6]

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)

#12


0  

Here is Whatangs answer if you want to get both sorted lists (python3).

如果您想要得到两个已排序的列表(python3),那么这里是Whatangs的答案。

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']

Just remember Zx and Zy are tuples. I am also wandering if there is a better way to do that.

记住Zx和Zy是元组。如果有更好的办法,我也在流浪。

Warning: If you run it with empty lists it crashes.

警告:如果你用空列表运行它,它会崩溃。

#13


0  

I have created a more general function, that sorts more than two lists based on another one, inspired by @Whatang's answer.

我创建了一个更通用的函数,根据@Whatang的答案,根据另一个列表对多个列表进行排序。

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

相关文章