Python 就地插入列表(或数组)
我正在用Python运行一个脚本,需要在数组(或列表)的某些索引位置插入新的数字。问题是,很明显,当我插入新的数字时,索引位置是无效的。有没有一种聪明的方法可以一次在索引位置插入新值?或者,唯一的解决方案是在我添加时增加索引号(索引对的第一个值) 测试代码片段示例:Python 就地插入列表(或数组),python,arrays,numpy,indexing,list-comprehension,Python,Arrays,Numpy,Indexing,List Comprehension,我正在用Python运行一个脚本,需要在数组(或列表)的某些索引位置插入新的数字。问题是,很明显,当我插入新的数字时,索引位置是无效的。有没有一种聪明的方法可以一次在索引位置插入新值?或者,唯一的解决方案是在我添加时增加索引号(索引对的第一个值) 测试代码片段示例: original_list = [0, 1, 2, 3, 4, 5, 6, 7] insertion_indices = [1, 4, 5] new_numbers = [8, 9, 10] pairs = [(insertion_
original_list = [0, 1, 2, 3, 4, 5, 6, 7]
insertion_indices = [1, 4, 5]
new_numbers = [8, 9, 10]
pairs = [(insertion_indices[i], new_numbers[i]) for i in range(len(insertion_indices))]
for pair in pairs:
original_list.insert(pair[0], pair[1])
结果:
[0, 8, 1, 2, 9, 10, 3, 4, 5, 6, 7]
鉴于我想要:
[0, 8, 1, 2, 3, 9, 4, 10, 5, 6, 7]
按向后顺序插入这些值。像这样:
original_list = [0, 1, 2, 3, 4, 5, 6, 7]
insertion_indices = [1, 4, 5]
new_numbers = [8, 9, 10]
new = zip(insertion_indices, new_numbers)
new.sort(reverse=True)
for i, x in new:
original_list.insert(i, x)
其工作原理基于以下观察结果:
在
列表的开头插入一个值
会将所有其他值的索引偏移1。但在末尾插入一个值,索引保持不变。因此,如果您从插入具有最大索引(10
)的值开始,然后继续“向后”操作,则不必更新任何索引。每次插入后,将所需索引增加1
original_list = [0, 1, 2, 3, 4, 5, 6, 7]
insertion_indices = [1, 4, 5]
new_numbers = [8, 9, 10]
for i in range(len(insertion_indices)):
original_list.insert(insertion_indices[i]+i,new_numbers[i])
print(original_list)
输出
[0, 8, 1, 2, 3, 9, 4, 10, 5, 6, 7]
#Required list
[0, 8, 1, 2, 3, 9, 4, 10, 5, 6, 7]
在for循环之前添加以下内容:
for i in range(len(insertion_indices)):
insertion_indices[i]+=i
被NumPy标记,并且由于输入被称为列表/数组,所以您可以简单地使用内置的- 为了将这个理论作为一个定制的理论(主要是为了性能),我们可以使用mask,就像这样-
def insert_numbers(original_list,insertion_indices, new_numbers):
# Length of output array
n = len(original_list)+len(insertion_indices)
# Setup mask array to selecrt between new and old numbers
mask = np.ones(n,dtype=bool)
mask[insertion_indices+np.arange(len(insertion_indices))] = 0
# Setup output array for assigning values from old and new lists/arrays
# by using mask and inverted mask version
out = np.empty(n,dtype=int)
out[mask] = original_list
out[~mask] = new_numbers
return out
对于列表输出,附加.tolist()
样本运行-
In [83]: original_list = [0, 1, 2, 3, 4, 5, 6, 7]
...: insertion_indices = [1, 4, 5]
...: new_numbers = [8, 9, 10]
...:
In [85]: np.insert(original_list, insertion_indices, new_numbers)
Out[85]: array([ 0, 8, 1, 2, 3, 9, 4, 10, 5, 6, 7])
In [86]: np.insert(original_list, insertion_indices, new_numbers).tolist()
Out[86]: [0, 8, 1, 2, 3, 9, 4, 10, 5, 6, 7]
对10000x
缩放数据集进行运行时测试-
In [184]: original_list = range(70000)
...: insertion_indices = np.sort(np.random.choice(len(original_list), 30000, replace=0)).tolist()
...: new_numbers = np.random.randint(0,10, len(insertion_indices)).tolist()
...: out1 = np.insert(original_list, insertion_indices, new_numbers)
...: out2 = insert_numbers(original_list, insertion_indices, new_numbers)
...: print np.allclose(out1, out2)
True
In [185]: %timeit np.insert(original_list, insertion_indices, new_numbers)
100 loops, best of 3: 5.37 ms per loop
In [186]: %timeit insert_numbers(original_list, insertion_indices, new_numbers)
100 loops, best of 3: 4.8 ms per loop
让我们用数组作为输入进行测试-
In [190]: original_list = np.arange(70000)
...: insertion_indices = np.sort(np.random.choice(len(original_list), 30000, replace=0))
...: new_numbers = np.random.randint(0,10, len(insertion_indices))
...: out1 = np.insert(original_list, insertion_indices, new_numbers)
...: out2 = insert_numbers(original_list, insertion_indices, new_numbers)
...: print np.allclose(out1, out2)
True
In [191]: %timeit np.insert(original_list, insertion_indices, new_numbers)
1000 loops, best of 3: 1.48 ms per loop
In [192]: %timeit insert_numbers(original_list, insertion_indices, new_numbers)
1000 loops, best of 3: 1.07 ms per loop
性能迅速提升,因为在转换到列表时没有运行时开销。不那么优雅,但也可以工作:使用numpy ndarray,每次递增指示:
import numpy as np
original_list = [0, 1, 2, 3, 4, 5, 6, 7]
insertion_indices = [1, 4, 5]
new_numbers = [8, 9, 10]
pairs = np.array([[insertion_indices[i], new_numbers[i]] for i in range(len(insertion_indices))])
for pair in pairs:
original_list.insert(pair[0], pair[1])
pairs[:, 0] += 1
@我猜是
插入索引的divaker输入错误。这是一个很好的答案!谢谢你的两个选择!性能是一个问题,因此定制的功能非常棒!
import numpy as np
original_list = [0, 1, 2, 3, 4, 5, 6, 7]
insertion_indices = [1, 4, 5]
new_numbers = [8, 9, 10]
pairs = np.array([[insertion_indices[i], new_numbers[i]] for i in range(len(insertion_indices))])
for pair in pairs:
original_list.insert(pair[0], pair[1])
pairs[:, 0] += 1