2012-12-17 74 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'] 

有一個整齊的,更 'Python化' 方式這樣做?還是應該堅持我擁有的?對編程風格的任何更正或反饋是值得歡迎的,我是新手,並試圖學習最佳實踐。

回答

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()內置功能組iterables的指數,所以當你通過一幫兩個元素的元組如上,你會得到一個元組的兩個元素的列表,其中第一個元組包含每個元組的第一個元素從catalog,而第二個元組包含來自catalog的每個元組的第二個元素。

在快速timeit測試zip()版本勝過一個循環的方式,當我和百萬對測試:

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

它簡潔而簡單,但它的性能如何?在任何其他語言中創建一個十億個參數將是可怕的。 –

+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

一個元組對於我的使用來說可以做得很好,但是謝謝你徹底! –