查找和替换列表中的元素


273

我必须搜索一个列表,然后用一个元素替换所有出现的元素。到目前为止,我在代码方面的尝试使我无处可寻,做到这一点的最佳方法是什么?

例如,假设我的列表具有以下整数

>>> a = [1,2,3,4,5,1,2,3,4,5,1]

我需要将所有出现的数字1替换为值10,所以我需要的输出是

>>> a = [10, 2, 3, 4, 5, 10, 2, 3, 4, 5, 10]

因此,我的目标是将数字1的所有实例替换为数字10。


11
顺便问一下,这是做什么用的?
2010年

Answers:


250
>>> a= [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1]
>>> for n, i in enumerate(a):
...   if i == 1:
...      a[n] = 10
...
>>> a
[10, 2, 3, 4, 5, 10, 2, 3, 4, 5, 10]

15
这是一个糟糕且非常不符合Python的解决方案。考虑使用列表理解。
AdHominem,2013年

203
如果不是Python的话,这很好。考虑使用列表理解。
让·弗朗索瓦·科贝特

考虑使用列表理解,例如下面的@outis!
AMC

6
这比列表理解要好,不是吗?它执行就地更新,而不是生成新列表。
neverendingqs

@neverendingqs:否。在翻译操作中占主导地位的是操作,而理解则较少。理解性能稍好,尤其是在通过替换条件的元素比例更高的情况下。有一些时间安排:ideone.com/ZrCy6z
user2357112支持Monica

517

尝试使用列表推导三元运算符

>>> a=[1,2,3,1,3,2,1,1]
>>> [4 if x==1 else x for x in a]
[4, 2, 3, 4, 3, 2, 4, 4]

9
但这不会改变,a对吧?我认为OP想要a改变
Dula

10
@Dula您可以执行a = [4,如果x == 1则x表示x在a中的位置],这将影响
Alekhya Vemavarapu

@Dula:关于是否a应该变异的问题尚不清楚,但是(如Alekhya所示)在使用列表推导时处理这两种情况都是微不足道的。
outis

34
如果要突变,a则应该这样做a[:] = [4 if x==1 else x for x in a](请注意完整列表片段)。只需执行即可a =创建一个aid()原始列表不同(身份)的新列表
Chris_Rands 17-4-25

39

列表理解效果很好,使用enumerate循环可以节省一些内存(b / c操作实际上已就位)。

还有功能编程。查看地图用法:

>>> a = [1,2,3,2,3,4,3,5,6,6,5,4,5,4,3,4,3,2,1]
>>> map(lambda x: x if x != 4 else 'sss', a)
[1, 2, 3, 2, 3, 'sss', 3, 5, 6, 6, 5, 'sss', 5, 'sss', 3, 'sss', 3, 2, 1]

17
+1。这太糟糕了lambdamap被认为是非Python的。
outis 2010年

4
我不确定lambda或map本质上是非Python语言的,但是我同意列表理解比将二者结合使用更干净,更易读。
damzam

7
我并不认为它们本身是非Python的,但是很多人都这样做,包括Guido van Rossum(artima.com/weblogs/viewpost.jsp?thread=98196)。这是那些宗派的事情之一。
2010年

35

如果您要替换多个值,则还可以使用字典:

a = [1, 2, 3, 4, 1, 5, 3, 2, 6, 1, 1]
dic = {1:10, 2:20, 3:'foo'}

print([dic.get(n, n) for n in a])

> [10, 20, 'foo', 4, 10, 5, 'foo', 20, 6, 10, 10]

1
如果n找不到,这不会抛出错误dic吗?
尼尔·

3
@ user2914540我改善了您的答案,因此,如果n找不到,它可以工作。我希望你不要介意。您的try/except解决方案不好。
jrjc

哦,是的,那更好。
roipoussiere

1
@jrjc @roipoussiere用于就地替换,try-except至少快50%!看看这个答案
生命平衡

4
if n in dic.keys()性能不好。使用if n in dic或者dic.get(n,n)(默认值)
让·弗朗索瓦·法布尔

12
>>> a=[1,2,3,4,5,1,2,3,4,5,1]
>>> item_to_replace = 1
>>> replacement_value = 6
>>> indices_to_replace = [i for i,x in enumerate(a) if x==item_to_replace]
>>> indices_to_replace
[0, 5, 10]
>>> for i in indices_to_replace:
...     a[i] = replacement_value
... 
>>> a
[6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6]
>>> 

中速但非常明智的方法。请查看我的答案中的时间安排。
dawg

10
a = [1,2,3,4,5,1,2,3,4,5,1,12]
for i in range (len(a)):
    if a[i]==2:
        a[i]=123

您可以使用for和while循环;但是,如果您知道内置的枚举功能,则建议使用枚举。1个


1
当您需要对列表项执行更复杂的操作时,这是唯一明智的(可读的)方法。例如,如果每个列表项都是一个长字符串,则需要某种搜索和替换。
not2qubit

8

所有轻易更换110a = [1,2,3,4,5,1,2,3,4,5,1]一个可以使用下面的一行拉姆达+地图相结合,与“看,妈妈,没有如果或者维权!” :

# This substitutes all '1' with '10' in list 'a' and places result in list 'c':

c = list(map(lambda b: b.replace("1","10"), a))


迄今为止最慢的方法。您lambda在每个列表元素上都调用一个...
dawg,

4

以下是Python 2.x中非常直接的方法

 a = [1,2,3,4,5,1,2,3,4,5,1]        #Replacing every 1 with 10
 for i in xrange(len(a)):
   if a[i] == 1:
     a[i] = 10  
 print a

此方法有效。欢迎发表评论。希望能帮助到你 :)

也请尝试了解outisdamzam的解决方案的工作方式。列表压缩和lambda函数是有用的工具。


3

我知道这是一个非常老的问题,并且有很多方法可以解决。我发现较简单的一种是使用numpy包。

import numpy

arr = numpy.asarray([1, 6, 1, 9, 8])
arr[ arr == 8 ] = 0 # change all occurrences of 8 by 0
print(arr)

3

我的用例已替换None为一些默认值。

我已经定时提出了解决此问题的方法,包括@kxr-using str.count

使用Python 3.8.1在ipython中测试代码:

def rep1(lst, replacer = 0):
    ''' List comprehension, new list '''

    return [item if item is not None else replacer for item in lst]


def rep2(lst, replacer = 0):
    ''' List comprehension, in-place '''    
    lst[:] =  [item if item is not None else replacer for item in lst]

    return lst


def rep3(lst, replacer = 0):
    ''' enumerate() with comparison - in-place '''
    for idx, item in enumerate(lst):
        if item is None:
            lst[idx] = replacer

    return lst


def rep4(lst, replacer = 0):
    ''' Using str.index + Exception, in-place '''

    idx = -1
    # none_amount = lst.count(None)
    while True:
        try:
            idx = lst.index(None, idx+1)
        except ValueError:
            break
        else:
            lst[idx] = replacer

    return lst


def rep5(lst, replacer = 0):
    ''' Using str.index + str.count, in-place '''

    idx = -1
    for _ in range(lst.count(None)):
        idx = lst.index(None, idx+1)
        lst[idx] = replacer

    return lst


def rep6(lst, replacer = 0):
    ''' Using map, return map iterator '''

    return map(lambda item: item if item is not None else replacer, lst)


def rep7(lst, replacer = 0):
    ''' Using map, return new list '''

    return list(map(lambda item: item if item is not None else replacer, lst))


lst = [5]*10**6
# lst = [None]*10**6

%timeit rep1(lst)    
%timeit rep2(lst)    
%timeit rep3(lst)    
%timeit rep4(lst)    
%timeit rep5(lst)    
%timeit rep6(lst)    
%timeit rep7(lst)    

我得到:

26.3 ms ± 163 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
29.3 ms ± 206 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
33.8 ms ± 191 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
11.9 ms ± 37.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
11.9 ms ± 60.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
260 ns ± 1.84 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
56.5 ms ± 204 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

str.index实际上,使用内部比任何手动比较都快。

我不知道测试4中的异常是否比使用更费力str.count,差异似乎可以忽略不计。

请注意,map()(测试6)返回迭代器而不是实际列表,因此测试7。


3

list.index()与其他答案中提出的单步迭代方法相比,在长列表和罕见情况下,使用它的速度大约快3倍。

def list_replace(lst, old=1, new=10):
    """replace list elements (inplace)"""
    i = -1
    try:
        while 1:
            i = lst.index(old, i + 1)
            lst[i] = new
    except ValueError:
        pass

这是我找到的最快的方法。请查看我的答案中的时间安排。大!
dawg

2

您可以在python中简单地使用列表理解:

def replace_element(YOUR_LIST, set_to=NEW_VALUE):
    return [i
            if SOME_CONDITION
            else NEW_VALUE
            for i in YOUR_LIST]

对于您的情况,要将所有出现的1替换为10,代码片段将如下所示:

def replace_element(YOUR_LIST, set_to=10):
    return [i
            if i != 1  # keeps all elements not equal to one
            else set_to  # replaces 1 with 10
            for i in YOUR_LIST]

3
尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。也请尽量不要在代码中加入解释性注释,这会降低代码和解释的可读性!
菲诺

-1

仅查找和替换一项

ur_list = [1,2,1]     # replace the first 1 wiz 11

loc = ur_list.index(1)
ur_list.remove(1)
ur_list.insert(loc, 11)

----------
[11,2,1]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.