在python中基于单个列表的排序对多个列表进行排序

在python中基于单个列表的排序对多个列表进行排序,python,itertools,Python,Itertools,我是一个python新手,我被一个相当简单的问题打动了——我正在寻找最有效的方法来解决这个问题。因此,我有以下5个列表: a,b,c,d,score 上面的列表都有相同的大小(在我的例子中是500)a、b、c、d是字符串列表,分数是int列表 我想做的是根据分数的升序或降序排序a、b、c、d。因此,我首先希望根据降序模式对分数进行排序,然后根据排序后的分数列表对a、b、c、d中的相应元素进行排序(顺序相同) 我想用enumerate来实现这一点,但我想知道这里是否可以使用itertools来提

我是一个python新手,我被一个相当简单的问题打动了——我正在寻找最有效的方法来解决这个问题。因此,我有以下5个列表:

a,b,c,d,score
上面的列表都有相同的大小(在我的例子中是500)<代码>a、b、c、d是字符串列表,
分数
int
列表

我想做的是根据
分数的升序或降序排序
a、b、c、d
。因此,我首先希望根据降序模式对
分数进行排序,然后根据排序后的分数列表对
a、b、c、d
中的相应元素进行排序(顺序相同)

我想用
enumerate
来实现这一点,但我想知道这里是否可以使用
itertools
来提高速度和效率

如果这是一个101问题,任何关于如何实现这一点的指导都将不胜感激和抱歉

sorted_lists = sorted(izip(a, b, c, d, score), reverse=True, key=lambda x: x[4])
a, b, c, d, score = [[x[i] for x in sorted_lists] for i in range(5)]
在第一步中,
zip
将列表放在一起。这将从每个列表中获取第一个元素并将它们放入一个元组中,将该元组附加到一个新列表中,然后对每个列表中的第二个元素执行相同的操作,依此类推。然后,我们按照第五个元素对这个元组列表进行排序(这是从传递到
key
参数的匿名函数中得到的)。我们设置
reverse=True
,使列表递减

在第二步中,我们使用一些嵌套的列表理解和元组解包来拆分列表。我们制作了一个新的列表列表,其中每个内部列表都是
排序列表中每个元组的所有第一个元素。您可以按如下一行完成此操作,但我认为将其分为两部分可能更清楚:

a, b, c, d, score = izip(*sorted(izip(a, b, c, d, score), reverse=True,
                         key=lambda x: x[4]))
下面是一个返回元组列表的通用函数,其中元组是排序列表:

def sort_lists_by(lists, key_list=0, desc=False):
    return izip(*sorted(izip(*lists), reverse=desc,
                 key=lambda x: x[key_list]))

如果您正在做大量的数值计算或数组操作,那么使用
numpy
可能值得一试。使用numpy阵列很容易解决此问题:

In [1]: import numpy as np
In [2]: a = ['hi','hello']
In [3]: b = ['alice','bob']
In [4]: c = ['foo','bar']
In [5]: d = ['spam','eggs']
In [6]: score = [42,17]
在此基础上,以
(a,b,c,d,score)
格式列出元组列表,并用一个数据类型
(str,str,str,int)
存储每个元组,您甚至可以给它们命名
('a','b','c','d','score')
以便以后访问它们:

In [7]: data = np.array(zip(a,b,c,d,score),
   ...:         dtype = [('a','S5'),('b','S5'),('c','S5'),('d','S5'),('score',int)]
   ...:     )

In [8]: data
Out[8]: 
array([('hi', 'alice', 'foo', 'spam', 42),
       ('hello', 'bob', 'bar', 'eggs', 17)], 
      dtype=[('a', 'S5'), ('b', 'S5'), ('c', 'S5'), ('d', 'S5'), ('score', '<i8')])
要对它们进行排序,只需给出要排序的字段的名称:

In [11]: sdata = np.sort(data, order='score')

In [12]: sdata
Out[12]: 
array([('hello', 'bob', 'bar', 'eggs', 17),
       ('hi', 'alice', 'foo', 'spam', 42)], 
      dtype=[('a', 'S5'), ('b', 'S5'), ('c', 'S5'), ('d', 'S5'), ('score', '<i8')])

In [13]: sdata['b']
Out[13]: 
array(['bob', 'alice'], 
      dtype='|S5')
[11]中的
:sdata=np.sort(数据,order='score')
在[12]中:sdata
出[12]:
数组([('hello','bob','bar','eggs',17),
('hi'、'alice'、'foo'、'spam',42)],

数据类型=[('a','S5'),('b','S5'),('c','S5'),('d','S5'),('score','Please,请看这里的类似问题:哪个是重复的。然而,如果列表很大并且python==2,那么
it.izip
将比
zip
更好。感谢EML提供了非常棒的解决方案-我只是想知道-是否有比中更通用的解决方案,其中
x[4]
range(5)
可以避免吗?我之所以问这个问题,是因为一个人可能有5个以上的列表。我不确定它是否有助于我理解何时对值进行硬编码:(编辑以添加通用函数。
范围(5)
只是用来指定子列表中每个元素的索引,因此我们可以在将每个子列表压缩到一起后将它们重新分解出来。
x[4]
只是指示我们对所有其他列表进行排序时所依据的列表。在通用函数中,这些列表被替换。有趣的是,
zip
将嵌套列表转置。类似于转置数组的功能。
izip
的输出基本上与
zip
相同,但没有为en分配大量新内存要构建一个组合列表,它会创建一个“生成器”,基本上一次输出一个产品,尽可能地回收内存。它使用更少的内存,在大多数情况下速度更快。这是Ray Hettinger的一篇精彩演讲,他简要地提到了这一点:好的,明白了。只需将它们作为列表传递,我假设类似
[a,b,c,d,score]
In [11]: sdata = np.sort(data, order='score')

In [12]: sdata
Out[12]: 
array([('hello', 'bob', 'bar', 'eggs', 17),
       ('hi', 'alice', 'foo', 'spam', 42)], 
      dtype=[('a', 'S5'), ('b', 'S5'), ('c', 'S5'), ('d', 'S5'), ('score', '<i8')])

In [13]: sdata['b']
Out[13]: 
array(['bob', 'alice'], 
      dtype='|S5')