我有1000个元素的列表。现在,我需要从该列表中删除1st,2nd,4th,8th,16th,32nd等元素。这是我的解决方法
i = 0
while pow(2,i) < len(arr):
del arr[pow(2,i) - 1 - i]
i += 1
但是我认为这似乎是一些不好的代码。有没有更优雅的方法来获得相同的结果?
答案 0 :(得分:1)
您需要撤消您的迭代;从最高值开始删除幂。从大于列表长度的下一个最大幂2开始,然后从那里向下移:
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
答案 1 :(得分:1)
numpy.delete
从数组开始,以大小随机生成,例如1000
:
import numpy as np
a = np.random.randint(100, size=(1000))
我们首先确定数组大小内的2的最大幂:
max_power = np.ceil(np.log2(len(a)))
此示例中max_power
的内容为10
。
现在我们可以创建一个具有2的幂的数组,代表要删除的索引:
exponents = np.arange(1, max_power)
indices = np.power(np.full(len(exponents), 2), exponents).astype(np.int)
索引数组包含array([ 2, 4, 8, 16, 32, 64, 128, 256, 512])
。
现在,我们可以继续删除这些索引:
result = np.delete(a, indices)
%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)
答案 2 :(得分:0)
那又怎么样:
/* generating a random array from a source array, algorithm */
function createRandomArray(srcArray, amount) {
var rndArray = []; // random array
while (rndArray.length < amount) { // how many random items?
// generating a random index
const random_index = Math.floor(Math.random() * srcArray.length);
// if random array doesn't have random index then...
if (!rndArray.includes(random_index)) {
// push the current item from source array with random inex
rndArray.push(srcArray[random_index]);
// then remove the selected item from source array with random inex
srcArray.splice(random_index, 1);
}
}
return rndArray; // the output of this function is a an array with random items
}
const sourceArray = [1,2,3,4,5,6,7,8,9,0];
print(createRandomArray(sourceArray, 5));
// output [6, 1, 8, 2, 7]
答案 3 :(得分:0)
您还可以反向迭代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).bit_length() - 1
是可以删除的2的最高指数。
1 << i
只是pow(2, i)
(整数)。