Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/365.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 - Fatal编程技术网

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

Python 更改列表的指定索引的最佳方法,python,Python,我想立即替换列表中的某些元素 假设我们有以下列表: list = [1, 2, 3, 4, 5, 6] idx = [1, 3, 4] new = [100, 200, 300] 我想用新值替换列表中的元素1、3、4。例如: list[idx] = new 最后的列表是=>[1100,3200,300,6] 我知道你可以在Matlab中以这种方式使用它,但是想知道我在Python中应该做什么吗 注意:我知道可以使用循环并执行此操作 编辑:我想使用纯python解决方案 L = [1, 2,

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

假设我们有以下列表:

list = [1, 2, 3, 4, 5, 6]
idx = [1, 3, 4]
new = [100, 200, 300]
我想用新值替换列表中的元素1、3、4。例如:

list[idx] = new
最后的列表是=>[1100,3200,300,6]

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

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

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

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)]

python的方法是使用zip:


Python本身不支持matlab风格的数组操作,但如果您对这种编码风格感兴趣,可以研究numpy,请参见@abarnert的答案

既然您正在寻找类似Matlab的解决方案,那么您很有可能真的应该在这里使用。事实上,如果您这样做,就可以完全按照您的要求编写代码:

>>> 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还为您提供了方便的多维数组,以及访问大量高级函数库的权限,特别是如果您包括类似的附加库的话。另外,您通常会获得性能优势,例如6倍的速度和0.25倍的空间

如果您想要一个纯Python解决方案,那么在Python中实现这么多NumPy或者您需要的那么多并不难。您可以用任何方式编写自己的数组类。特别要注意的是,a[idx]=new调用a.。\uuuu setitem\uuuu 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
对于idx和value具有不同长度的情况,您可能需要添加一些错误处理。你可以从第一原则中找出最好的规则,或者从看NumPy做什么开始,然后决定你做什么和不想复制什么


当然,这一实现的核心代码与alexis的答案非常相似并不是偶然的,因为我们所做的只是包装逻辑,所以您只需编写一次,而不是每次需要时编写一次。

首先,为什么要使用rangelenidx而不是zipidx,new?另外,第二个版本与第一个版本有相同的循环,是什么让你觉得它更慢?@abarnert:第二个版本在列表中查找元素,这需要时间;因此,经济放缓。zip绝对是比我的第一个loopAh更好的版本,我没有看到你这样做;是的,比较慢。但是你可以很容易地编写一个listcomp,它可能会更快,除了像这样的非常小的输入,它可能会更慢,但谁在乎呢?。我可能过于谨慎了,因为有太多的答案错误地暗示,对列表进行适当的修改通常比构建一个新的列表要快,因为这在C语言中是正确的,而在Python中通常是错误的,甚至更不相关;为没有更仔细地阅读而道歉。或者根本不改变现有的列表;类似于d=dictzipidx的东西,新的;L=[d.getidx,idx的值,enumerateL中的值]。在许多情况下,新列表更合适,但问题是更新列表。当然,但通常最好的方法是使用新列表,然后使用L=或L[:]=…在这种情况下,这可能是真的,也可能不是真的,但是对于新手来说,了解这两种方法是值得的,这样他们就可以选择正确的方法。我同意。不过,在这种情况下,更新非常简单,如果需要一个新列表,我会先复制一个副本,然后将编辑应用到副本上。Numpy是一个很好的库,我以前使用过它。但是我想要一个纯python的解决方案:@mehD:好吧,你可以用纯python编写这么多的NumPy;事实上,这很琐碎。请参阅我的最新答案。
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