使用 Python 替换 list 中的值

我有一个列表,其中我希望用 Nothing 替换条件()返回 True 的值。

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

例如,如果条件检查 bool (项% 2)应该返回:

[None, 1, None, 3, None, 5, None, 7, None, 9, None]

做到这一点最有效的方法是什么?

856629 次浏览
>>> L = range (11)
>>> [ x if x%2 == 1 else None for x in L ]
[None, 1, None, 3, None, 5, None, 7, None, 9, None]

用一个列表内涵建立一个新的列表:

new_items = [x if x % 2 else None for x in items]

如果你愿意,你可以就地修改原始列表,但这并不能真正节省时间:

items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for index, item in enumerate(items):
if not (item % 2):
items[index] = None

下面是(Python 3.6.3)演示非时间保存的计时:

In [1]: %%timeit
...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
...: for index, item in enumerate(items):
...:     if not (item % 2):
...:         items[index] = None
...:
1.06 µs ± 33.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)


In [2]: %%timeit
...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
...: new_items = [x if x % 2 else None for x in items]
...:
891 ns ± 13.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Python 2.7.6次计时:

In [1]: %%timeit
...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
...: for index, item in enumerate(items):
...:     if not (item % 2):
...:         items[index] = None
...:
1000000 loops, best of 3: 1.27 µs per loop
In [2]: %%timeit
...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
...: new_items = [x if x % 2 else None for x in items]
...:
1000000 loops, best of 3: 1.14 µs per loop
ls = [x if (condition) else None for x in ls]

对 OP 在评论中提出的一个问题即兴发挥,比如:

如果我有一个发电机 范围(11)中的值代替 是否可以更换 在发电机中的值是多少?

当然,小菜一碟:

def replaceiniter(it, predicate, replacement=None):
for item in it:
if predicate(item): yield replacement
else: yield item

只需将任何迭代(包括调用生成器的结果)作为第一个参数传递,这个谓词用于判断是否必须将一个值替换为第二个参数,然后开始运行。

例如:

>>> list(replaceiniter(xrange(11), lambda x: x%2))
[0, None, 2, None, 4, None, 6, None, 8, None, 10]

还有一个办法:

>>> L = range (11)
>>> map(lambda x: x if x%2 else None, L)
[None, 1, None, 3, None, 5, None, 7, None, 9, None]

这个可能会有帮助。

test_list = [5, 8]
test_list[0] = None
print test_list
#prints [None, 8]

如果希望在适当的位置替换值,可以 用列表中的值更新原始列表 通过赋予原文的整个片段来理解。

data = [*range(11)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
id_before = id(data)
data[:] = [x if x % 2 else None for x in data]
data
# Out: [None, 1, None, 3, None, 5, None, 7, None, 9, None]
id_before == id(data)  # check if list is still the same
# Out: True

如果有多个名字指向原始列表, 例如,您在更改列表之前编写了 data2=data 跳过指定为 data的切片符号, data将重新绑定到指向新创建的列表,而 data2仍然指向原始的未更改列表。

data = [*range(11)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
data2 = data
id_before = id(data)
data = [x if x % 2 else None for x in data]  # no [:] here
data
# Out: [None, 1, None, 3, None, 5, None, 7, None, 9, None]
id_before == id(data)  # check if list is still the same
# Out: False
data2
# Out: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

注意: 这并不是推荐一个比另一个更好 (更改列表是否到位) ,但行为你应该知道。