Python 如何根据索引从包含多个列表的列表创建新列表

Python how to create new lists from a list containing multiple lists depending on indexes

我有一个存储包含 5 个元素的列表的列表。我想创建 5 个新列表来存储每个索引的元素。我有以下代码,但它似乎不是聪明的方法。

>>> stats
[['1', '0', '36', '36', '3'], ['10', '0', '41', '77', '5'], ['1', '0', '631', '631', '63'], ['1', '0', '98', '98', '9'], ['9', '0', '52', '81', '6'], ['2', '0', '111', '167', '13'], ['1', '0', '98', '98', '9'], ['1', '0', '92', '92', '9'], ['2', '0', '241', '287', '26'], ['1', '0', '210', '210', '21'], ['2', '0', '336', '358', '34'], ['2', '0', '49', '57', '5'], ['5', '0', '52', '148', '7'], ['2', '0', '46', '76', '6'], ['3', '0', '33', '50', '4'], ['7', '0', '47', '70', '6'], ['1', '0', '94', '94', '9'], ['1', '0', '65', '65', '6'], ['1', '0', '66', '66', '6'], ['1', '0', '429', '429', '42'], ['1', '0', '337', '337', '33'], ['12', '0', '49', '126', '6'], ['1', '0', '47', '47', '4'], ['1', '0', '63', '63', '6'], ['1', '0', '79', '79', '7'], ['2', '0', '96', '100', '9'], ['1', '0', '36', '36', '3'], ['1', '0', '69', '69', '6'], ['6', '0', '44', '67', '5'], ['3', '0', '269', '385', '31'], ['2', '0', '78', '115', '9'], ['2', '0', '49', '52', '5'], ['3', '0', '26', '134', '9'], ['2', '0', '255', '561', '40'], ['1', '0', '75', '75', '7'], ['1', '0', '59', '59', '5'], ['2', '0', '59', '64', '6'], ['1', '0', '86', '86', '8'], ['1', '0', '63', '63', '6'], ['2', '0', '79', '100', '8'], ['4', '0', '825', '888', '86'], ['1', '0', '82', '82', '8'], ['3', '0', '65', '94', '7'], ['1', '0', '88', '88', '8'], ['1', '0', '344', '344', '34'], ['1', '0', '286', '286', '28'], ['1', '0', '73', '73', '7'], ['3', '0', '42', '69', '5'], ['1', '0', '151', '151', '15'], ['1', '0', '286', '286', '28'], ['2', '0', '47', '59', '5'], ['9', '0', '15', '41', '2'], ['2', '0', '343', '355', '34'], ['1', '0', '305', '305', '30'], ['1', '0', '238', '238', '23'], ['2', '0', '974', '2101', '153'], ['2', '0', '138', '142', '14'], ['7', '0', '45', '70', '5'], ['1', '0', '39', '39', '3']]
>>>
>>> num_requests,num_failures,min_response_time,max_response_time,avg_response_time = [], [], [], [], []
>>>
>>> for l in stats:
...  num_requests.append(l[0])
...  num_failures.append(l[1])
...  min_response_time.append(l[2])
...  max_response_time.append(l[3])
...  avg_response_time.append(l[4])
...
>>> num_requests
['1', '10', '1', '1', '9', '2', '1', '1', '2', '1', '2', '2', '5', '2', '3', '7', '1', '1', '1', '1', '1', '12', '1', '1', '1', '2', '1', '1', '6', '3', '2', '2', '3', '2', '1', '1', '2', '1', '1', '2', '4', '1', '3', '1', '1', '1', '1', '3', '1', '1', '2', '9', '2', '1', '1', '2', '2', '7', '1']

它可以存储在一个列表中,该列表存储5个子列表。

解决方案

只需使用 zip*:

(num_requests, num_failures, min_response_time, max_response_time, 
 avg_response_time) = zip(*stats)

这给你元组。如果需要列表,请转换为列表:

(num_requests, num_failures, min_response_time, max_response_time, 
 avg_response_time) = (list(x) for x in zip(*stats))

详情

一个较短的例子:

>>> data = [[1, 2, 3], [10, 20, 30], [100, 200, 300]]
>>> a, b, c = zip(*data)
>>> a
(1, 10, 100)
>>> b
(2, 20, 200)
>>> c
(3, 30, 300)

这相当于:

a, b, c = zip(data[0], data[1], data[2])

但适用于任意数量的子列表。

左边使用的是元组拆包。例如,这个:

x, y, z = (10, 20, 30)

10 分配给 x,将 20 分配给 y,将 30 分配给 z

性能

测量它有多快。

版本 append:

%%timeit
num_requests,num_failures,min_response_time,max_response_time,avg_response_time = [], [], [], [], []

for l in stats:
    num_requests.append(l[0])
    num_failures.append(l[1])
    min_response_time.append(l[2])
    max_response_time.append(l[3])
    avg_response_time.append(l[4])

10000 loops, best of 3: 51 µs per loop

版本zip

%%timeit
(num_requests, num_failures, min_response_time, max_response_time, 
     avg_response_time) = zip(*stats)

100000 loops, best of 3: 8.58 µs per loop

大约快五倍。

将元组转换为列表需要更长的时间:

%%timeit
(num_requests, num_failures, min_response_time, max_response_time, 
 avg_response_time) = (list(x) for x in zip(*stats))

100000 loops, best of 3: 13.3 µs per loop

仍然快四倍。