2013-08-01 48 views
4

我有三個列表:過濾兩份名單同時

del_ids = [2, 4] 
ids = [3, 2, 4, 1] 
other = ['a', 'b', 'c', 'd'] 

,我的目標是消除del_ids,結果是

ids = [3, 1] 
other = ['a', 'd'] 

我試圖做一個面具元素,以保持(mask = [id not in del_ids for id in ids] ),我打算在這兩個列表上應用此掩碼。

但我覺得這不是一個pythonic解決方案。你能告訴我怎樣才能做得更好嗎?

回答

8

拉鍊,過濾並再次解壓縮:

ids, other = zip(*((id, other) for id, other in zip(ids, other) if id not in del_ids)) 

zip()呼叫對每個id與相應other元件,發電機表達濾除其中iddel_ids被列出的任何一對,並且zip(*..)然後引子再次將剩餘的對放入單獨的列表中。

演示:

>>> del_ids = [2, 4] 
>>> ids = [3, 2, 4, 1] 
>>> other = ['a', 'b', 'c', 'd'] 
>>> zip(*((id, other) for id, other in zip(ids, other) if id not in del_ids)) 
[(3, 1), ('a', 'd')] 
+0

感謝您的回答,您可以告訴我的明星是什麼,在這種情況呢?這種形式的理解對我來說是新的。 :O –

+0

@BarnabasSzabolcs:它將序列(來自生成器表達式的所有對)作爲單獨的參數應用於'zip()'函數。 'zip()'見'zip(pair1,pair2,pair3等)',然後將所有這些對拉成兩個列表。 –

+0

@BarnabasSzabolcs:'(.. for .. in ..)'構造是一個生成器表達式。這很像列表理解('[.. for .. in ..]'),除非它不會在內存中首先創建一個新列表。 –

1

壓縮,過濾器,解壓:

ids, other = zip(*filter(lambda (id,_): not id in del_ids, zip(ids, other))) 
+0

@Martijn:過濾器返回一個正好2元組的過濾列表,所以我可以安全地解壓它們。該死的你是對的,我做了更正。 –

+0

是的,直到您的過濾器返回多於或少於2個元組。不要複製我的解決方案,直到你明白它的作用。 :-P –

+0

@MartijnPieters:我在看過你之前寫了答案。我想偉大的思想家都認爲一樣; --P –