用Python替换列表中的选定元素

时间:2013-01-16 02:18:13

标签: python list list-comprehension slice

我有一个列表:mylist = [0, 0, 0, 0, 0]

我只想用一个公共号码A = 100替换所选元素,比如第一个,第二个和第四个。

一种方法:

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

我正在寻找一种单行或更简单的方法来实现这一目标。更为通用和灵活的答案是可取的。

6 个答案:

答案 0 :(得分:8)

特别是因为你正在替换list中相当大的一部分,我会不可避免地这样做:

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

在Python中故意制作一个新的list是一个单行,而变异list需要一个显式的循环。通常,如果您不知道自己想要哪一个,则需要新的list。 (在某些情况下,它更慢或更复杂,或者你有一些其他代码引用相同的list并需要看到它变异,或者其他什么,这就是为什么它“通常”而不是“总是”。)

如果你想不止一次这样做,我会把它包装成一个函数,正如Volatility建议的那样:

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

答案 1 :(得分: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])

答案 2 :(得分:1)

如果你不反对使用np.ndarray

,Numpy支持这一点
>>> a = np.zeros(5)
>>> a[[0,1,3]] = 100
>>> a
array([ 100.,  100.,    0.,  100.,    0.])

答案 3 :(得分: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]

答案 4 :(得分: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中的map returns an iterator。您可以使用six模块从Python 2.x模拟Python 3.x中map的行为,并结合collections.deque(再次由@abarnert建议),您可以实现相同的输出而无需在内存中创建额外的列表,因为可以包含最多deque项的0将丢弃从map迭代器接收的所有内容(请注意six迭代器1}},使用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]

答案 5 :(得分:0)

我喜欢列表理解:

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