2012-03-23 56 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