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:
解释道:
-
zip
the twolist
s. - 压缩这两个列表。
- create a new, sorted
list
based on thezip
usingsorted()
. - 根据使用排序()的zip创建一个新的排序列表。
- using a list comprehension extract the first elements of each pair from the sorted, zipped
list
. - 使用列表理解从排序的压缩列表中提取每对的第一个元素。
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:
解释道:
-
zip
the twolist
s. - 压缩这两个列表。
- create a new, sorted
list
based on thezip
usingsorted()
. - 根据使用排序()的zip创建一个新的排序列表。
- using a list comprehension extract the first elements of each pair from the sorted, zipped
list
. - 使用列表理解从排序的压缩列表中提取每对的第一个元素。
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