2011-08-18 87 views
5

所以,我有以下形式的數組:爲什麼我不能從一個列表理解中得到兩個列表?

[(1, u'first_type', u'data_gid_1'), 
(2, u'first_type', u'data_gid_2'), 
(3, u'first_type', u'data_gid_3'), 
(4, u'first_type', u'data_gid_4')] 

現在我想提取的第一個和每個內部列表分成單獨的列表的最後一個元素。所以如果我這樣做:

>>> ids = [dat[0] for dat in all_data] 
>>> gds = [dat[2] for dat in all_data] 

這工作正如我所料。不過,我試圖將這兩個合併成一個呼叫,像:

(ids, gds) = [(dat[0], dat[2]) for dat in all_data] 

然而,這失敗的: ValueError: too many values to unpack

所以任何人都可以解釋爲什麼發生這種情況,如果我所試圖做的甚至有可能。

問候, 波格丹

+1

將它作爲兩行保留有什麼問題嗎?我的意思是有時候很清楚。 –

+1

沒有錯,這仍然是我正在使用的解決方案,我只是想了解爲什麼我會爲將來的使用收到錯誤。 – Bogdan

+0

@Bogdan這真是光榮。我會給你一個評論的+1。 – cwallenpoole

回答

8

它不工作,因爲[(dat[0], dat[2]) for dat in all_data]的長度是一樣的all_data的lenght,這是不一樣的長度元組(ids, gds)

試試這個:

(ids, gds) = zip(*[(dat[0], dat[2]) for dat in all_data]) 

甚至更​​短:

(ids, gds) = zip(*all_data)[::2] 

正如另一個答案指出,idsgds現在將元組,所以如果你需要列出,這樣做:

(ids, gds) = map(list, zip(*all_data)[::2]) 



zip(*something)是一個相當常見的python語言。如果你看作爲一個矩陣列表的列表,即

l = [[1, 2, 3], 
    [4, 5, 6]] 

然後zip(*l)調換該矩陣:

zip(*l) == [(1, 4), 
      (2, 5), 
      (3, 6)] 

*是這樣的:some_func(*some_list)解壓some_list這樣函數是效果以some_list的元素作爲參數調用。所以zip(*l)zip([1, 2, 3], [4, 5, 6])相同。 Here's python教程的相關部分。

zip作用就像一個zipper,因此得名,所以它返回與這些元素的列表:的給定的參數的所有第一元素的元組,隨後所有的第二元素的元組等

+1

不錯。雖然有一個更好的解釋來幫助OP:「'解包太多的值'會發生,因爲您試圖將4元素列表分配給2元元組。」 +1。 –

+0

感謝您的輸入。進來了。 – Bogdan

+0

有意思問一下zip()究竟是什麼。感謝澄清。一旦時間到期將會接受。 – Bogdan

1

[(dat[0], dat[2]) for dat in all_data]表示您正在創建元組列表(dat[0],dat[2])。這並不意味着你有兩個清單,一個是d[0],另一個是d[2]

您可以簡單地使用zip,但那會導致元組。如果你想列表,您必須申請list的結果:

下面
(ids, gds) = map(list,zip(*[(dat[0], dat[2]) for dat in a])) 
4

代碼也將做的伎倆:

data = [(1, u'first_type', u'data_gid_1'), 
(2, u'first_type', u'data_gid_2'), 
(3, u'first_type', u'data_gid_3'), 
(4, u'first_type', u'data_gid_4')] 

ids, gds = ([row[i] for row in data] for i in [0,2]) 
0

由於要創建兩個單獨的列表,試試這個:

ids, dgs = [(dat[0]) for dat in all_data], [(dat[2]) for dat in all_data] 

,或者你可以將它解壓到你所使用的命令單列表:

x = [(dat[0], dat[2]) for dat in all_data] 
相關問題