Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/304.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 就地插入列表(或数组)_Python_Arrays_Numpy_Indexing_List Comprehension - Fatal编程技术网

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_

我正在用Python运行一个脚本,需要在数组(或列表)的某些索引位置插入新的数字。问题是,很明显,当我插入新的数字时,索引位置是无效的。有没有一种聪明的方法可以一次在索引位置插入新值?或者,唯一的解决方案是在我添加时增加索引号(索引对的第一个值)

测试代码片段示例:

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