我有一个列表:mylist = [0, 0, 0, 0, 0]
更换出现选择列表中的元素在Python
我只希望替换选择的元素,比方说第一,第二,和一个共同的数量,A = 100
第四。要做到这一点
方式一:
mylist[:2] = [A]*2
mylist[3] = A
mylist
[100, 100, 0, 100, 0]
我要寻找一个班轮,或者更简单的方法来做到这一点。更普遍和灵活的答案是可取的。
我有一个列表:mylist = [0, 0, 0, 0, 0]
更换出现选择列表中的元素在Python
我只希望替换选择的元素,比方说第一,第二,和一个共同的数量,A = 100
第四。要做到这一点
方式一:
mylist[:2] = [A]*2
mylist[3] = A
mylist
[100, 100, 0, 100, 0]
我要寻找一个班轮,或者更简单的方法来做到这一点。更普遍和灵活的答案是可取的。
特别是因为您要更换的一个相当大的块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
这是你在找什么?列出要更改的索引,然后遍历该列表以更改值。
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]
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])
+1。除了更普遍之外,我认为这是做可变替换的最可读的方式,尽管(或者可能是因为)不是单线程的。 – abarnert
numpy的支持这一点,如果你不反对使用np.ndarray
:
>>> a = np.zeros(5)
>>> a[[0,1,3]] = 100
>>> a
array([ 100., 100., 0., 100., 0.])
+1。即使这并不直接回答OP的问题(我不确定它没有),但是每当你发现自己处理数字序列并且看起来比应该更难时,你应该问的第一个问题可能是“我是否反对在这里使用'np.ndarray'?” – abarnert
不是这一个巨大的风扇,但你可以试试这个(虽然我觉得所有上述得多简洁易读):从可疑的可读性
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中的map
returns 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]
主要与此相关的问题是,在Python 3中,它不起作用,因为您只需取回一个永远不会迭代的迭代器。较小的问题是,在Python 2中,它构建了一个你不需要的列表。你可以通过明确地执行list(map(...))来解决第一个问题。或者你可以通过使用'six.map'并将结果传递给一个'iter_discard'函数来解决这两个问题,你可以将它作为'collections.deque(it,max_size = 0)'来实现。这是一个更多的想法,你应该把它放在一个解决方案,你不是一个巨大的粉丝,当然... – abarnert
@abarnert迟到+1到你的答案(一如既往的信息),和伟大的观点关于这个实现(从未考虑过将'map'的结果传递给'iter_discard'函数)。我会为后人的缘故添加一个更新,并且一如既往地感谢有用的信息:) – RocketDonkey
我真的希望'iter_discard'是3.x标准库的一部分。反对它的观点是,这将鼓励人们使用'map'来代替结果(而且,如果你真的想要,'deque'技巧已经被添加到'itertools'文档的某处)。我可以买那个......但是对于这些问题,人们总是这样做(然后想用他们可以找到的每个Python版本来“计时”结果)。 – abarnert
我喜欢列表理解:
[100 if index in [1, 4] else 0 for index, x in enumerate(mylist) ]
这个怎么样? mylist [:2],mylist [3] = [A] * 2,A –