Python 如何删除嵌套列表的第n个索引?

Python 如何删除嵌套列表的第n个索引?,python,Python,我一直在为那件事挠头 我有一个嵌套列表,格式如下: ( (value1, value2, value3), (value1, value2, value3), ... (value1, value2, value3)) 现在我想把它归结为: ( (value1, value2), (value1, value2), ... (value1, value2)) 简而言之,尝试删除每个嵌套列表的第三个元素 在Python中是否可以直接执行此操作?只需理解列表即可: >>> x

我一直在为那件事挠头

我有一个嵌套列表,格式如下:

( (value1, value2, value3), (value1, value2, value3), ... (value1, value2, value3))
现在我想把它归结为:

( (value1, value2), (value1, value2), ... (value1, value2))
简而言之,尝试删除每个嵌套列表的第三个元素


在Python中是否可以直接执行此操作?

只需理解列表即可:

>>> x = [(1, 2, 3), (1, 2, 3), (1, 2, 3)]
>>> x = [(a, b) for (a, b, c) in x]
[(1, 2), (1, 2), (1, 2)]
outerlist = [sublist[:-1] for sublist in outerlist]

使用列表理解:

>>> x = [(1, 2, 3), (1, 2, 3), (1, 2, 3)]
>>> x = [(a, b) for (a, b, c) in x]
[(1, 2), (1, 2), (1, 2)]
outerlist = [sublist[:-1] for sublist in outerlist]
这使用切片删除每个包含的子列表的最后一个元素

上面创建的是一个列表,而不是元组;以下操作将再次创建元组:

outertuple = tuple(sublist[:-1] for sublist in outertuple)
与解包和重新打包元组相比,切片子列表需要更少的操作码,从而更快地获得结果

使用元组演示:

>>> outertuple = ((1, 2, 3), (4, 5, 6), (7, 8, 9))
>>> tuple(sublist[:-1] for sublist in outertuple)
((1, 2), (4, 5), (7, 8))
使用列表演示:

>>> outerlist = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [sublist[:-1] for sublist in outerlist]
[[1, 2], [4, 5], [7, 8]]
最后但并非最不重要的是,对列表理解的内部循环进行字节码分解,以表明切片使用的操作码少于解包和重新打包:

>>> import dis
>>> def foo(x): return [sublist[:-1] for sublist in x]
... 
>>> def bar(x): return [(a, b) for (a, b, c) in x]
... 
>>> dis.dis(foo)
  1           0 BUILD_LIST               0
              3 LOAD_FAST                0 (x)
              6 GET_ITER            
        >>    7 FOR_ITER                16 (to 26)
             10 STORE_FAST               1 (sublist)
             13 LOAD_FAST                1 (sublist)
             16 LOAD_CONST               1 (-1)
             19 SLICE+2             
             20 LIST_APPEND              2
             23 JUMP_ABSOLUTE            7
        >>   26 RETURN_VALUE        
>>> dis.dis(bar)
  1           0 BUILD_LIST               0
              3 LOAD_FAST                0 (x)
              6 GET_ITER            
        >>    7 FOR_ITER                27 (to 37)
             10 UNPACK_SEQUENCE          3
             13 STORE_FAST               1 (a)
             16 STORE_FAST               2 (b)
             19 STORE_FAST               3 (c)
             22 LOAD_FAST                1 (a)
             25 LOAD_FAST                2 (b)
             28 BUILD_TUPLE              2
             31 LIST_APPEND              2
             34 JUMP_ABSOLUTE            7
        >>   37 RETURN_VALUE        
11对14操作码。这是一个额外的解包序列和两个存储快速操作码,以及一个构建元组操作码和切片+2

这些差异使得拆包和打包速度大大降低:

>>> import timeit
>>> test = [(42, 69, 180) for _ in xrange(1000)]
>>> timeit.timeit('f(x)', 'from __main__ import test as x, foo as f', number=10000)
1.1722910404205322
>>> timeit.timeit('f(x)', 'from __main__ import test as x, bar as f', number=10000)
1.6375460624694824
使用地图:

l = [[0,1,2], [1,2,3]]
print map(lambda l : l[:-1], l)
# Outputs [[0, 1], [1, 2]]
假设所有子列表的长度均为3

如果要对元组执行此操作:

l = ((0,1,2), (1,2,3))
print tuple(map(lambda l : l[:-1], l))
# Outputs ((0, 1), (1, 2))
试试这个:

[a[ :-1] for a in b]
或者这个:

[a[:n]+a[n+1:] for a in b]

[1,2,1,2,1,2]

这里有元组;列表有[]个方括号。您是希望将其放在适当的位置还是获得一个单独的实例?为什么要进行向下投票?它起作用了。遍历列表会得到子列表,而del listname[indexyouwantgone]会去掉给定的元素。他没有说他一定要删除最后一个元素。可能是因为OP似乎有元组,而元组是不可变的?如果他想更改元组,他可能不应该使用元组。使用>>@unkulunkulu有点奇怪:但是对于序列中的每个子列表,切片要比解包和重新打包快得多-请注意,在Python3中,您可以做一些疯狂的事情,例如[head for*head,tail in x]来提取除最后一个之外的所有内容。@ascobol-Err,是的,方法不对。这将教会我在凌晨2点尝试编码……是的,成功了!非常感谢。你从我这里得到+1。然而,在这种情况下,选择看起来更好的,而不是更快的-担心这肯定会导致担心过早优化。@Yuushi:通常,我同意你的观点,但在列表理解方面,你要小心。这是循环的内部部分,事先了解技术之间的差异会有所帮助。此外,切片与解包/重新打包的可读性几乎不差,是吗?抱歉,我并没有暗示它可读性差,老实说,它可能更可读一些,只是除非这真的成为分析器中的瓶颈,否则我不会担心它。但是有了这些分析,当它成为一个问题时,肯定是有用的。@Yuushi:我把这看作是基本知识;比如知道使用集合进行成员资格测试要比使用大列表快得多,知道何时使用itertools、bisect、heapq等+1来解释切片和重新打包之间的差异。如果您已经有了重新打包解决方案,并且想要切换到切片解决方案,那么这只是过早的优化。由于OP两者都没有,所以它只是一个更优的解决方案。
x = [(1, 2, 3), (1, 2, 3), (1, 2, 3)]
>>> [i[:2] for i in x ]