更改列表的指定索引的最佳方法

时间:2014-10-10 17:50:59

标签: python

我想立即替换列表中的一些元素。

假设我们有这些列表:

list = [1, 2, 3, 4, 5, 6]
idx = [1, 3, 4]
new = [100, 200, 300]

我想将list中的元素1,3,4替换为new值。例如:

list[idx] = new

所以最后的清单是=> [1, 100, 3, 200, 300, 6]

我知道你可以在Matlab中以这种方式使用它,但想知道我应该在Python中做什么?

注意:我知道可以使用循环并执行此操作。


编辑:我想使用纯python解决方案。

3 个答案:

答案 0 :(得分:5)

" pythonic"方法是使用zip

for i, n in zip(idx, new):
    L[i] = n

Python本身并不支持matlab风格的数组操作,但如果您对该编码风格感兴趣,可以查看numpy(参见@ abarnert的回答)。

答案 1 :(得分:2)

L = [1, 2, 3, 4, 5, 6]
idx = [1, 3, 4]
new = [100, 200, 300]
for i in range(len(idx)):
    L[idx[i]] = new[i]

没有循环的稍慢版本:

L = [1, 2, 3, 4, 5, 6]
idx = [1, 3, 4]
new = [100, 200, 300]
L = [num if i not in idx else new[i] for i,num in enumerate(L)]

答案 2 :(得分:2)

由于您正在寻找类似Matlab的解决方案,因此您很有可能在这里使用NumPy。事实上,如果你以这种方式做事,你可以准确地编写你想要的代码:

>>> import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6])
>>> idx = [1, 3, 4]
>>> new = [100, 200, 300]
>>> a[idx] = new
>>> a
array([  1, 100,   3, 200, 300,   6])

除了为您提供Matlab-ish元素操作符和函数外,NumPy还为您提供方便的多维数组,并可访问大型高级函数库(特别是如果您包含SciPy等附属库)。此外,您通常可以获得性能优势,例如6倍速和0.25倍空间。


如果你想要一个纯Python解决方案,那么 很难在Python中实现这么多的NumPy(或者你需要的话)。您可以以任何方式编写自己的Array课程emulates a container type。请特别注意a[idx] = new调用a.__setitem__(idx, new)。您可能希望以与list相同的方式处理单个数字和切片,但是没有什么可以阻止您处理list拒绝的其他类型。例如:

def __setitem__(self, idx, value):
    if isinstance(idx, collections.abc.Iterable):
        for i, v in zip(idx, value):
            self.lst[i] = v
    else:
        self.lst[idx] = value

(您可能希望为idxvalue长度不同的情况添加一些错误处理。您可以根据第一原则制定最佳规则,或者首先看看NumPy做了什么,然后决定你做了什么,不想复制......)

当然,这个实现的内容与alexis的答案非常相似并不是偶然的,因为我们所做的就是完成逻辑,所以你只需要写一次,而不是每次都需要它。