I am trying to sort a list of lists in Python by the first row (specifically not using Numpy, I know there are many solutions using Numpy but this is a question that specifically asks for a way without using Numpy)
我试图通过第一行在Python中对列表进行排序(特别是不使用Numpy,我知道有很多使用Numpy的解决方案,但这是一个特别要求不使用Numpy的方法的问题)
Here is my list of lists:
这是我的清单列表:
listOfLists = [ ['m', 'e', 'l', 't', 's'],
['g', 'p', 's', 'k', 't'],
['y', 'q', 'd', 'h', 's'] ]
I am looking to sort this list 1) alphabetically BUT 2) only by the first list item, the vertical slices should just follow the order of the first list item. For example:
我希望按字母顺序排序此列表1)但仅由第一个列表项排序,垂直切片应该遵循第一个列表项的顺序。例如:
newListofLists = [ ['e', 'l', 'm', 's', 't'],
['p', 's', 'g', 't', 'k'],
['q', 'd', 'y', 's', 'h'] ]
The first item in listOfLists is 'melts', which is then sorted alphabetically to become 'elmst'. The rest of the items in the list of list aren't sorted alphabetically, rather they are 'following' the switch and sort pattern of the first item in the list.
listOfLists中的第一项是'melts',然后按字母顺序排序成'elmst'。列表列表中的其余项目不按字母顺序排序,而是“跟随”列表中第一项的切换和排序模式。
I may be being ridiculous but I've spent hours on this problem (which forms part of a larger program). I have tried slicing the first item from the list of lists and sorting it alphabetically on its own, then comparing this to a slice of the first list in the list of lists that HASN'T been sorted, and comparing positions. But I just can't seem to get anything working.
我可能很荒谬,但我花了好几个小时来处理这个问题(这是一个更大的程序的一部分)。我尝试从列表列表中切割第一个项目并按字母顺序对其进行排序,然后将其与未排序的列表列表中的第一个列表的切片进行比较,并比较位置。但我似乎无法得到任何有用的东西。
2 个解决方案
#1
11
You can transpose the list using zip
, sort the transpose, and then transpose that list back into one of the correct dimensions.
您可以使用zip转置列表,对转置进行排序,然后将该列表转换回正确的维度之一。
listOfLists = [ ['m', 'e', 'l', 't', 's'],
['g', 'p', 's', 'k', 't'],
['y', 'q', 'd', 'h', 's'] ]
print(list(zip(*sorted(zip(*listOfLists)))))
# [('e', 'l', 'm', 's', 't'), ('p', 's', 'g', 't', 'k'), ('q', 'd', 'y', 's', 'h')]
Edit:
编辑:
As @StevenRumbalski points out in the comments, the above will completely sort the vertical slices (by first letter, then second letter, etc), instead of sorting them stably by first letter (sorting by first letter, then by relative order in the input). I'll reproduce his solution here for visibility:
正如@StevenRumbalski在评论中指出的那样,上面将完全排序垂直切片(通过第一个字母,然后是第二个字母等),而不是通过第一个字母稳定地排序它们(按首字母排序,然后按输入中的相对顺序排序) )。我将在这里重现他的解决方案以获得可见性:
from operator import itemgetter
list(map(list, zip(*sorted(zip(*listOfLists), key=itemgetter(0)))))
#2
1
numpy
is the way to go for both performance and readability:
numpy是兼顾性能和可读性的方法:
import numpy as np
listOfLists = [ ['m', 'e', 'l', 't', 's'],
['g', 'p', 's', 'k', 't'],
['y', 'q', 'd', 'h', 's'] ]
lol = np.array(listOfLists)
lol[:, np.argsort(listOfLists[0])]
# array([['e', 'l', 'm', 's', 't'],
# ['p', 's', 'g', 't', 'k'],
# ['q', 'd', 'y', 's', 'h']],
# dtype='<U1')
A non-numpy
solution:
一个非numpy解决方案:
idx = sorted(range(len(lol[0])), key=lol[0].__getitem__)
[list(map(lol[j].__getitem__, idx)) for j in range(len(lol))]
#1
11
You can transpose the list using zip
, sort the transpose, and then transpose that list back into one of the correct dimensions.
您可以使用zip转置列表,对转置进行排序,然后将该列表转换回正确的维度之一。
listOfLists = [ ['m', 'e', 'l', 't', 's'],
['g', 'p', 's', 'k', 't'],
['y', 'q', 'd', 'h', 's'] ]
print(list(zip(*sorted(zip(*listOfLists)))))
# [('e', 'l', 'm', 's', 't'), ('p', 's', 'g', 't', 'k'), ('q', 'd', 'y', 's', 'h')]
Edit:
编辑:
As @StevenRumbalski points out in the comments, the above will completely sort the vertical slices (by first letter, then second letter, etc), instead of sorting them stably by first letter (sorting by first letter, then by relative order in the input). I'll reproduce his solution here for visibility:
正如@StevenRumbalski在评论中指出的那样,上面将完全排序垂直切片(通过第一个字母,然后是第二个字母等),而不是通过第一个字母稳定地排序它们(按首字母排序,然后按输入中的相对顺序排序) )。我将在这里重现他的解决方案以获得可见性:
from operator import itemgetter
list(map(list, zip(*sorted(zip(*listOfLists), key=itemgetter(0)))))
#2
1
numpy
is the way to go for both performance and readability:
numpy是兼顾性能和可读性的方法:
import numpy as np
listOfLists = [ ['m', 'e', 'l', 't', 's'],
['g', 'p', 's', 'k', 't'],
['y', 'q', 'd', 'h', 's'] ]
lol = np.array(listOfLists)
lol[:, np.argsort(listOfLists[0])]
# array([['e', 'l', 'm', 's', 't'],
# ['p', 's', 'g', 't', 'k'],
# ['q', 'd', 'y', 's', 'h']],
# dtype='<U1')
A non-numpy
solution:
一个非numpy解决方案:
idx = sorted(range(len(lol[0])), key=lol[0].__getitem__)
[list(map(lol[j].__getitem__, idx)) for j in range(len(lol))]