首页 > 解决方案 > 从列表中删除每个第 n 个元素的更好方法

问题描述

我有一个包含 1000 个元素的列表。现在我需要从该列表中删除第 1、第 2、第 4、第 8、第 16、第 32 等元素。这是我的解决方案

i = 0
while pow(2,i) < len(arr):
    del arr[pow(2,i) - 1 - i]
    i += 1

但我认为这似乎是一些糟糕的代码。有没有更优雅的方法来获得相同的结果?

标签: pythonpython-3.x

解决方案


你需要反转你的迭代;从最高值向下删除权力。从大于列表长度的二的次幂开始,然后从那里向下移动:

i = 2 ** len(arr).bit_length()  # next higher power-of-two > len
while i > 1:
    i >>= 1
    del arr[i - 1]  # 4th index is 3, 8th index is 7, etc.

另一种选择:您可以生成一个新列表,而不是就地从列表中删除:

[v for i, v in enumerate(arr, 1) if i & (i - 1)]

这使用了一个事实,即 2 的幂只有一个位集;如果你用数字 - 1 掩盖它,你得到零。

演示:

>>> arr = list(range(1, 33))  # 6 values to remove, 1, 2, 4, 8, 16 and 32
>>> arr
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
>>> len(arr)
32
>>> [v for i, v in enumerate(arr, 1) if i & (i - 1)]
[3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
>>> i = 2 ** len(arr).bit_length()  # highest power-of-two >= len
>>> while i > 1:
...     i >>= 1
...     del arr[i - 1]  # 4th index is 3, 8th index is 7, etc.
...
>>> arr
[3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
>>> arr == [v for i, v in enumerate(range(1, 33), 1) if i & (i - 1)]
True
>>> len(arr)
26

推荐阅读