Python 从列表中删除第n个元素的更好方法
我有1000个元素的列表。现在我需要从列表中删除第1、2、4、8、16、32等元素。这是我的解决办法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)
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)