2012-12-17 4 views
3

Можно создать дубликат:
A Transpose/Unzip Function in PythonРасщепление список последовательностей в два списка эффективно

У меня есть список последовательностей, каждая последовательность имеет два элемента. Я хотел бы превратить это в два списка.

catalog = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')] 

Прямо сейчас я просто делаю это:

names = [] 
vals = [] 

for product in catalog: 
     names.append(product[0]) 
     vals.append(product[1]) 

print (names) 
print (vals) 

, который выводит два списка, и работает просто отлично:

['abc', 'foo', 'bar', 'test'] 
['123', '456', '789', '1337'] 

Есть аккуратнее, более 'вещий' путь делать это? Или я должен придерживаться того, что у меня есть? Любые исправления или отзывы о стиле программирования приветствуются, я новичок и стараюсь изучить лучшие практики.

ответ

10
>>> catalog = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')] 
>>> names, vals = zip(*catalog) 
>>> names 
('abc', 'foo', 'bar', 'test') 
>>> vals 
('123', '456', '789', '1337') 

*catalog синтаксис здесь называется Unpacking Argument Lists и zip(*catalog) переводит на вызов zip(catalog[0], catalog[1], catalog[2], ...).

В zip() встроенных функциональных группы итерируемого по индексам, так что, когда вы проходите связку из двух элементов кортежей, как описаны выше, вы получите список из двух элементов кортежей, где первый кортеж содержит первый элемент каждого кортежа из catalog, а второй кортеж содержит второй элемент из каждого набора из catalog.

В тесте быстрого timeit версия zip() обгоняет циклический подход, когда я тестировал с 1.000.000 парами:

In [1]: catalog = [(i, i+1) for i in range(1000000)] 

In [2]: def with_zip(): 
    ...:  return zip(*catalog) 
    ...: 

In [3]: def without_zip(): 
    ...:  names, vals = [], [] 
    ...:  for name, val in catalog: 
    ...:   names.append(name) 
    ...:   vals.append(val) 
    ...:  return names, vals 
    ...: 

In [4]: %timeit with_zip() 
1 loops, best of 3: 176 ms per loop 

In [5]: %timeit without_zip() 
1 loops, best of 3: 250 ms per loop 
+0

Это идеальный вариант, спасибо! Раньше я никогда не слышал об этой функции. Я связываюсь с документацией для этой функции, для будущих читателей. http://docs.python.org/3.3/library/functions.html#zip –

+1

Это красноречиво и просто, но насколько оно выполнено? На любом другом языке создание zillion параметров было бы ужасно. –

+0

@MarkRansom - Я тоже об этом задумывался ... – mgilson

2

Конечно, использовать это:

lst = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')] 
tup1, tup2 = zip(*lst) 

выше будет возвращать пару кортежи с элементами. Если вам нужно списки, а затем использовать это:

lst = [('abc', '123'), ('foo', '456'), ('bar', '789'), ('test', '1337')] 
lst1, lst2 = map(list, zip(*lst)) 
+1

Кортеж будет отлично подходит для моего использования, но спасибо за тщательность! –

Смежные вопросы