преобразовать список кортежей нескольких списков в Python
Предположим, у меня есть список кортежей, и я хочу, чтобы преобразовать в несколько списков.
например, список кортежей
[(1,2),(3,4),(5,6),]
есть ли встроенная функция в Python, которая преобразует ее в:
[1,3,5],[2,4,6]
Это может быть простая программа. Но я просто любопытно о существовании такой встроенной функции в Python.
6 ответов:
встроенная функция
zip()почти делать то, что вы хотите:>>> zip(*[(1, 2), (3, 4), (5, 6)]) [(1, 3, 5), (2, 4, 6)]единственная разница в том, что вы получаете кортежи вместо списков. Вы можете конвертировать их в списки с помощью
map(list, zip(*[(1, 2), (3, 4), (5, 6)]))
С python docs:
zip () в сочетании с оператором * можно использовать для распаковки списка:
конкретный пример:
>>> zip((1,3,5),(2,4,6)) [(1, 2), (3, 4), (5, 6)] >>> zip(*[(1, 2), (3, 4), (5, 6)]) [(1, 3, 5), (2, 4, 6)]или, если вы действительно хотите списки:
>>> map(list, zip(*[(1, 2), (3, 4), (5, 6)])) [[1, 3, 5], [2, 4, 6]]
franklsf95 идет на производительность в своем ответе и выбирает
list.append(), но они не являются оптимальными.добавление списка понимания, я закончил со следующим:
def t1(zs): xs, ys = zip(*zs) return xs, ys def t2(zs): xs, ys = [], [] for x, y in zs: xs.append(x) ys.append(y) return xs, ys def t3(zs): xs, ys = [x for x, y in zs], [y for x, y in zs] return xs, ys if __name__ == '__main__': from timeit import timeit setup_string='''\ N = 2000000 xs = list(range(1, N)) ys = list(range(N+1, N*2)) zs = list(zip(xs, ys)) from __main__ import t1, t2, t3 ''' print(f'zip:\t\t{timeit('t1(zs)', setup=setup_string, number=1000)}') print(f'append:\t\t{timeit('t2(zs)', setup=setup_string, number=1000)}') print(f'list comp:\t{timeit('t3(zs)', setup=setup_string, number=1000)}')Это дало результат:
zip: 122.11585397789766 append: 356.44876132614047 list comp: 144.637765085659так что если вы после выступления, вы, вероятно, должны использовать
zip()хотя список понимания не слишком далеко позади. Выступлениеappendна самом деле довольно плохо по сравнению.
добавление к ответу Claudiu и Claudiu, и поскольку карта должна быть импортирована из itertools в python 3, вы также используете понимание списка, например:
[[*x] for x in zip(*[(1,2),(3,4),(5,6)])] >>> [[1, 3, 5], [2, 4, 6]]
несмотря на
*zipбыть более подходящие для Python, следующий код имеет гораздо более высокую производительность:xs, ys = [], [] for x, y in zs: xs.append(x) ys.append(y)также, когда исходный список
zsпустой*zipподнимет, но этот код может правильно обработать.Я только что провел быстрый эксперимент, и вот результат:
Using *zip: 1.54701614s Using append: 0.52687597sзапустить его несколько раз,
appendэто 3x - 4x быстрее, чемzip! Тестовый скрипт находится здесь:#!/usr/bin/env python3 import time N = 2000000 xs = list(range(1, N)) ys = list(range(N+1, N*2)) zs = list(zip(xs, ys)) t1 = time.time() xs_, ys_ = zip(*zs) print(len(xs_), len(ys_)) t2 = time.time() xs_, ys_ = [], [] for x, y in zs: xs_.append(x) ys_.append(y) print(len(xs_), len(ys_)) t3 = time.time() print('Using *zip:\t{:.8f}s'.format(t2 - t1)) print('Using append:\t{:.8f}s'.format(t3 - t2))Моя Версия Python:
Python 3.6.3 (default, Oct 24 2017, 12:18:40) [GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin Type "help", "copyright", "credits" or "license" for more information.
Comments