Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从列表中删除第n个元素的更好方法_Python_Python 3.x - Fatal编程技术网

Python 从列表中删除第n个元素的更好方法

Python 从列表中删除第n个元素的更好方法,python,python-3.x,Python,Python 3.x,我有1000个元素的列表。现在我需要从列表中删除第1、2、4、8、16、32等元素。这是我的解决办法 i = 0 while pow(2,i) < len(arr): del arr[pow(2,i) - 1 - i] i += 1 i=0 而pow(2,i)

我有1000个元素的列表。现在我需要从列表中删除第1、2、4、8、16、32等元素。这是我的解决办法

i = 0
while pow(2,i) < len(arr):
    del arr[pow(2,i) - 1 - i]
    i += 1
i=0
而pow(2,i)
但我认为这似乎是一些糟糕的代码。有没有更优雅的方法可以达到同样的效果?

那么:

powers_to_remove = [2**i for i in range(int(math.ceil(math.log(len(arr), 2))))]
result = [arr[i] for i in range(len(arr)) if i+1 not in powers_to_remove]
你需要逆转你的迭代;从最高值向下删除功率。从大于列表长度的下一个最高二次幂开始,然后从那里向下移动:

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)]
这利用了二的幂只有一个位集的事实;如果你用数字-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

您还可以反向迭代2的幂:

mx = (len(arr) - 1).bit_length() - 1

for idx in (1 << i for i in range(mx, -1, -1)):
    del arr[idx]
mx=(len(arr)-1)。位长度()
对于idx in(1)解决方案,使用
从数组开始,以大小随机生成,例如,
1000

import numpy as np
a = np.random.randint(100, size=(1000))
我们首先确定阵列大小内2的最大功率:

max_power = np.ceil(np.log2(len(a)))
本例中
max_power
的内容为
10

现在我们可以创建一个二次幂的数组,表示要删除的索引:

exponents = np.arange(1, max_power)
indices = np.power(np.full(len(exponents), 2), exponents).astype(np.int)
索引数组包含
数组([2,4,8,16,32,64,128,256,512])

现在,我们可以继续删除这些索引:

result = np.delete(a, indices)
时间比较:numpy和列表理解
@Aran Fey,你是对的,我把第n个位置和数组索引混合在一起。编辑并解决了。谢谢这需要建立一个O(logN)列表,然后每一步都对该列表进行包含测试。这使得这是一个O(NlogN)解决方案,需要O(logN)空间。你可以在O(logN)中轻松实现这一点没有任何额外空间的时间!因此,如果原始列表是
[a,b,c,d]
,那么结果应该是
[c]
还是
[c,d]
(这就是您的代码输出)?
%timeit np.delete(a, indices)
>>> 35.1 µs ± 2.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit [a[i] for i in range(len(a)) if i+1 not in powers_to_remove]
>>> 372 µs ± 25.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)