我必须在一个列表中搜索,并用另一个元素替换所有出现的元素。到目前为止,我在代码方面的尝试都没有取得什么进展,最好的方法是什么?
例如,假设我的列表有以下整数
>>> 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。
我必须在一个列表中搜索,并用另一个元素替换所有出现的元素。到目前为止,我在代码方面的尝试都没有取得什么进展,最好的方法是什么?
例如,假设我的列表有以下整数
>>> 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。
当前回答
列表理解工作得很好,使用enumerate进行循环可以节省一些内存(b/c操作基本上是在适当的位置完成的)。
还有函数式编程。参见map用法:
>>> 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]
其他回答
在长列表和很少出现的情况下,使用list.index()比其他答案中给出的单步迭代方法快3倍左右。
def list_replace(lst, old=1, new=10):
"""replace list elements (inplace)"""
i = -1
try:
while True:
i = lst.index(old, i + 1)
lst[i] = new
except ValueError:
pass
尝试使用列表推导式和条件表达式。
>>> 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]
我知道这是一个非常古老的问题,有无数种方法来解决它。我发现的更简单的方法是使用numpy包。
import numpy
arr = numpy.asarray([1, 6, 1, 9, 8])
arr[ arr == 8 ] = 0 # change all occurrences of 8 by 0
print(arr)
我的用例正在用一些默认值替换None。
我已经对这里给出的解决这个问题的方法进行了计时,包括@kxr的方法——使用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。
我可能是个笨蛋,但我会为它写一个单独的简单函数:
def convertElements( oldlist, convert_dict ):
newlist = []
for e in oldlist:
if e in convert_dict:
newlist.append(convert_dict[e])
else:
newlist.append(e)
return newlist
然后根据需要调用它,如下所示:
a = [1,2,3,4,5,1,2,3,4,5,1]
a_new = convertElements(a, {1: 10})
## OUTPUT: a_new=[10, 2, 3, 4, 5, 10, 2, 3, 4, 5, 10]