2013-01-16 42 views
7

我有一个列表:mylist = [0, 0, 0, 0, 0]更换出现选择列表中的元素在Python

我只希望替换选择的元素,比方说第一,第二,和一个共同的数量,A = 100第四。要做到这一点

方式一:

mylist[:2] = [A]*2 
mylist[3] = A 
mylist 
[100, 100, 0, 100, 0] 

我要寻找一个班轮,或者更简单的方法来做到这一点。更普遍和灵活的答案是可取的。

+0

这个怎么样? mylist [:2],mylist [3] = [A] * 2,A –

回答

7

特别是因为您要更换的一个相当大的块list,我会做这个不可改变:

mylist = [100 if i in (0, 1, 3) else e for i, e in enumerate(mylist)] 

这是故意在Python这使得新list是一个班轮,而变异的一个list需要一个显式循环。通常,如果你不知道你想要哪一个,你需要新的list。 (在某些情况下,它更慢或更复杂,或者你有一些其他代码引用了相同的list,并需要看到它发生了变异,或者其他,这就是为什么这是“通常”而不是“始终”。)

如果你想要做一次这样多,我包起来的功能,如波动说明:

def elements_replaced(lst, new_element, indices): 
    return [new_element if i in indices else e for i, e in enumerate(lst)] 

我个人很可能会使其成为一个发电机,因此产生一个迭代的,而不是返回一个列表,即使我永远不会需要这个,只是因为我这样愚蠢。但是,如果你真的需要它:

myiter = (100 if i in (0, 1, 3) else e for i, e in enumerate(mylist)) 

或者:

def elements_replaced(lst, new_element, indices): 
    for i, e in enumerate(lst): 
     if i in indices: 
      yield new_element 
     else: 
      yield e 
+0

关于新列表和变异的好解释。 – elwc

+0

有时我会错过'valarray :: gslice' – Abhijit

+0

@Abhijit:几乎所有的情况下,'valarray'在C++中都是有意义的,'numpy'在Python中是有意义的,'numpy'的扩展切片比几乎所有情况下都有'gslice'。例如,请参阅mgilson对此问题的回答。 (当然,“几乎所有”和“几乎所有”与“every”和“all”并不完全相同......但是我很少发现自己正在编写一些'numpy'代码并且缺少C++功能......) – abarnert

0

这是你在找什么?列出要更改的索引,然后遍历该列表以更改值。

els_to_replace = [0, 1, 3] 

mylist = [0, 0, 0, 0, 0] 

for index in els_to_replace: 
    mylist[index] = 100 


mylist 
Out[9]: [100, 100, 0, 100, 0] 
2
def replace_element(lst, new_element, indices): 
    for i in indices: 
     lst[i] = new_element 
    return lst 

这绝对是一个更通用的解决方案,而不是一个班轮虽然。例如,你的情况,你会打电话:

mylist = replace_element(mylist, 100, [0, 1, 3]) 
+0

+1。除了更普遍之外,我认为这是做可变替换的最可读的方式,尽管(或者可能是因为)不是单线程的。 – abarnert

1

numpy的支持这一点,如果你不反对使用np.ndarray

>>> a = np.zeros(5) 
>>> a[[0,1,3]] = 100 
>>> a 
array([ 100., 100., 0., 100., 0.]) 
+0

+1。即使这并不直接回答OP的问题(我不确定它没有),但是每当你发现自己处理数字序列并且看起来比应该更难时,你应该问的第一个问题可能是“我是否反对在这里使用'np.ndarray'?” – abarnert

0

不是这一个巨大的风扇,但你可以试试这个(虽然我觉得所有上述得多简洁易读):从可疑的可读性

In [22]: from operator import setitem 

In [23]: mylist = [0, 0, 0, 0, 0] 

In [24]: indeces_to_replace = [0, 1, 3] 

In [25]: _ = map(lambda x: setitem(mylist, x, 100), indeces_to_replace) 

In [26]: mylist 
Out[26]: [100, 100, 0, 100, 0] 

一边,需要进口,@abarnert指出了一些额外的问题,即map仍会创建一个不必要的列表(该列表会被_丢弃,但会被创建),并且它不能在Python 3中工作,因为Python 3.x中的mapreturns an iterator。您可以使用six模块来模拟Python 2中Python 3.x中map的行为。x以及与collections.deque(再次按照@abarnert的建议)结合使用时,可以在不创建内存中的附加列表的情况下实现相同的输出,因为可包含最多0项目将放弃从迭代器map收到的所有内容(注意six,map通过使用itertools.imap来模拟)。

同样,也完全没有必要永远使用这个 - 高于/低于每一个解决方案是更好:)

In [1]: from collections import deque 

In [2]: from six.moves import map 

In [3]: from operator import setitem 

In [4]: mylist = [0, 0, 0, 0, 0] 

In [5]: indeces_to_replace = [0, 1, 3] 

In [6]: deque(map(lambda x: setitem(mylist, x, 100), indeces_to_replace), maxlen=0) 
Out[6]: deque([], maxlen=0) 

In [7]: mylist 
Out[7]: [100, 100, 0, 100, 0] 
+0

主要与此相关的问题是,在Python 3中,它不起作用,因为您只需取回一个永远不会迭代的迭代器。较小的问题是,在Python 2中,它构建了一个你不需要的列表。你可以通过明确地执行list(map(...))来解决第一个问题。或者你可以通过使用'six.map'并将结果传递给一个'iter_discard'函数来解决这两个问题,你可以将它作为'collections.deque(it,max_size = 0)'来实现。这是一个更多的想法,你应该把它放在一个解决方案,你不是一个巨大的粉丝,当然... – abarnert

+0

@abarnert迟到+1到你的答案(一如既往的信息),和伟大的观点关于这个实现(从未考虑过将'map'的结果传递给'iter_discard'函数)。我会为后人的缘故添加一个更新,并且一如既往地感谢有用的信息:) – RocketDonkey

+0

我真的希望'iter_discard'是3.x标准库的一部分。反对它的观点是,这将鼓励人们使用'map'来代替结果(而且,如果你真的想要,'deque'技巧已经被添加到'itertools'文档的某处)。我可以买那个......但是对于这些问题,人们总是这样做(然后想用他们可以找到的每个Python版本来“计时”结果)。 – abarnert

0

我喜欢列表理解:

[100 if index in [1, 4] else 0 for index, x in enumerate(mylist) ]