简体   繁体   English

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

[英]Replacing selected elements in a list in Python

I have a list: mylist = [0, 0, 0, 0, 0] 我有一个列表: mylist = [0, 0, 0, 0, 0]

I only want to replace selected elements, say the first, second, and fourth by a common number, A = 100 . 我只想用一个公共数字A = 100替换所选元素,比如第一个,第二个和第四A = 100

One way to do this: 一种方法:

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

I am looking for a one-liner, or an easier method to do this. 我正在寻找一个单行或更简单的方法来做到这一点。 A more general and flexible answer is preferable. 更通用和灵活的答案是更可取的。

Especially since you're replacing a sizable chunk of the list , I'd do this immutably: 特别是因为你正在替换list相当大的一部分,我会不可改变地做到这一点:

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

It's intentional in Python that making a new list is a one-liner, while mutating a list requires an explicit loop. 在Python中故意制作一个新list是一个单行,而改变list需要一个显式循环。 Usually, if you don't know which one you want, you want the new list . 通常,如果您不知道自己想要哪一个,则需要新list (In some cases it's slower or more complicated, or you've got some other code that has a reference to the same list and needs to see it mutated, or whatever, which is why that's "usually" rather than "always".) (在某些情况下,它更慢或更复杂,或者你有一些其他代码引用了相同的list ,需要看到它变异,或者其他什么,这就是为什么“通常”而不是“总是”。)

If you want to do this more than once, I'd wrap it up in a function, as Volatility suggests: 如果你想不止一次这样做,我会把它包装成一个函数,正如Volatility建议的那样:

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

I personally would probably make it a generator so it yields an iteration instead of returning a list, even if I'm never going to need that, just because I'm stupid that way. 我个人可能会把它变成一个生成器,所以它产生一个迭代而不是返回一个列表,即使我永远不会需要它,只是因为我这样愚蠢。 But if you actually do need it: 但是,如果你真的需要它:

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

Or: 要么:

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

It's definitely a more general solution, not a one-liner though. 这绝对是一个更通用的解决方案,但不是单线程。 For example, in your case, you would call: 例如,在您的情况下,您将调用:

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

Numpy supports this if you're not opposed to using an np.ndarray : 如果你不反对使用np.ndarray Numpy支持这个:

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

Is this what you're looking for? 这是你在找什么? Make a list of the indexes you want to change, and then loop through that list to change the values. 列出要更改的索引,然后循环遍历该列表以更改值。

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]

Not a huge fan of this one, but you could try this (although I think all of the above are much more concise and easy to read): 不是这个的忠实粉丝,但你可以试试这个(虽然我认为以上所有内容都更简洁易读):

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]

Aside from the questionable readability and need for an import, @abarnert pointed out a few additional issues, namely that map still creates an unnecessary list (which is discarded with the _ but created nonetheless) and that it won't work in Python 3 because map returns an iterator in Python 3.x. 除了可疑的可读性和需要进口,@abarnert指出了一些额外的问题,即map仍然带来不必要的列表(它与丢弃_ ,但仍然创造了),而且它不会在Python 3工作,因为map在Python 3.x中返回一个迭代器 You can use the six module to simulate the behavior of map in Python 3.x from Python 2.x, and in combination with collections.deque (again as suggested by @abarnert), you can achieve the same output without creating the additional list in memory because a deque that can contain a maximum of 0 items will discard everything it receives from the map iterator (note that with six , map is simulated by using itertools.imap ). 您可以使用六个模块来模拟Python 3.x中Python 3.x中的map行为,并结合collections.deque (再次由@abarnert建议),您可以实现相同的输出而无需创建其他列表在内存中,因为一个最多可包含0项目的deque将丢弃它从map迭代器接收的所有内容(注意,有six ,使用itertools.imap模拟map )。

Again, there is absolutely no need to ever use this - every solution above/below is better :) 同样,绝对没有必要使用它 - 上面/下面的每个解决方案都更好:)

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]

我喜欢列表理解:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM