2012-03-23 58 views
7

我試圖從Python中的嵌套列表中刪除項目。我有一個嵌套列表如下:從嵌套列表中刪除項目Python

families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]] 

我想刪除在每個子列表是coorespond到主列表中的子表的索引位置的條目。所以,例如,我需要從第一個子列表中刪除0,從第二個子列表中刪除1,等等。我試圖使用列表解析來做到這一點。這是我曾嘗試:

familiesNew = [ [ families[i][j] for j in families[i] if i !=j ] for i in range(len(families)) ] 

本工程爲range(len(families))最多3個,但除此之外,我得到IndexError: list index out of range。我不知道爲什麼。有人可以給我一個如何做到這一點的想法。最好是單行(列表理解)。

謝謝。

回答

9

你幾乎說得對。只需更換families[i][j]j和它的作品:

>>> [ [ j for j in families[i] if i !=j ] for i in range(len(families)) ] 
[[1, 2], [0, 2, 3], [0, 1, 3, 4], [1, 2, 4, 5], [2, 3, 5, 6]] 

它可以寫成使用enumerate功能有點清潔:

>>> [[f for f in family if f != i] for i, family in enumerate(families)] 
[[1, 2], [0, 2, 3], [0, 1, 3, 4], [1, 2, 4, 5], [2, 3, 5, 6]] 

甚至使用remove,如果你不介意改變原來的列表:

>>> for i, family in enumerate(families): family.remove(i) 
+0

謝謝,我決定去與最後的選擇,因爲它事實上是可以的,需要更改到位名單。 – johntfoster 2012-03-25 02:51:38

3

這是否你想要做什麼?

familiesNew=[ filter(lambda x:x!=i,j) for i,j in enumerate(families) ] 

編輯

還要注意,你失敗的原因是因爲在外部列表([1, 2, 3, 4, 5])的第三個元素,你正在試圖獲得第五元素在你的for循環(for j in families[i] = = for j in [1,2,3,4,5]),但家庭[I]有長度爲5,這意味着最大的指數是4,很抱歉,如果這個解釋是有點不清楚......也許下面將幫助它清除掉一點:

families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]] 

def f(i,j): 
    print i,j,families[i] 
    return families[i][j] 
#THIS DOES NOT WORK -- but it will tell you where it failed. 
familiesNew = [ [ f(i,j) for j in families[i] if i !=j ] for i in range(len(families)) ] 
5

編輯的問題,刪除我的答案是解決了錯誤的問題。此外,增加了額外的答案被@Ashwini:

爲了比較:

root# python -m timeit 'families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]]' '[x.remove(ind) for ind,x in enumerate(families) ]' 
100000 loops, best of 3: 3.42 usec per loop  

root# python -m timeit -s 'families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]]' '[[f for f in family if f != i] for i, family in enumerate(families)]' 
100000 loops, best of 3: 4.87 usec per loop 

root# python -m timeit -s 'families = [[0, 1, 2],[0, 1, 2, 3],[0, 1, 2, 3, 4],[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]]' '[ filter(lambda x:x!=i,j) for i,j in enumerate(families) ]' 
100000 loops, best of 3: 7.99 usec per loop 

這些都是微秒,所以我想你想幹什麼就幹什麼是好的,除非你打算做這樣的

+0

我認爲這個語義不太對。這不是說,應該從每個子列表中刪除* index *'i'處的元素,而是刪除項目'i'本身。 – 2012-03-23 23:37:11

+0

這是一個聰明的伎倆,但我認爲它並沒有完全做它打算做的事情。 (如果外部列表的後面的元素是從0開始的序列,那麼這將起作用。 +1時間雖然。 – mgilson 2012-03-23 23:37:55

+0

我錯誤地誤讀了問題的意圖(並且隨後不檢查輸出是否匹配) – sberry 2012-03-24 00:27:55

2

如果要修改原來的列表,然後試試這個:

>>>[x.remove(ind) for ind,x in enumerate(families) ] 
>>>families 
[[1, 2], [0, 2, 3], [0, 1, 3, 4], [1, 2, 4, 5], [2, 3, 5, 6]] 
+0

這個答案很有趣,因爲它可以進行計算。據推測,它會返回一個無...的列表,但對於某些應用程序來說可能還行。 – mgilson 2012-03-23 23:45:12

+0

是的!這個列表理解將返回一個無長度== len(家庭)的列表並且將修改原始列表。 – 2012-03-23 23:52:42

+0

好的解決方案,雖然通常認爲使用列表理解對副作用是不禮貌的。 – 2012-03-24 04:42:42