如果我有一个matchCondition(x)
函数,我如何删除Python列表中符合该条件的第一个n
项?
一种解决方案是迭代每一项,将其标记为删除(例如,将其设置为None
),然后使用理解过滤列表。这需要遍历列表两次并改变数据。有没有一种更常用或更有效的方法来做到这一点?
n = 3
def condition(x):
return x < 5
data = [1, 10, 2, 9, 3, 8, 4, 7]
out = do_remove(data, n, condition)
print(out) # [10, 9, 8, 4, 7] (1, 2, and 3 are removed, 4 remains)
发布于 2016-09-20 03:25:17
使用itertools.filterfalse
和itertools.count
的单向方法
from itertools import count, filterfalse
data = [1, 10, 2, 9, 3, 8, 4, 7]
output = filterfalse(lambda L, c=count(): L < 5 and next(c) < 3, data)
然后是list(output)
,它为您提供了:
[10, 9, 8, 4, 7]
发布于 2016-09-20 03:03:49
编写一个生成器,它接受迭代值、条件和要丢弃的量。遍历数据并生成不满足条件的项。如果满足条件,则递增一个计数器,并且不产生该值。一旦计数器达到你想要丢弃的数量,就一定要放弃。
def iter_drop_n(data, condition, drop):
dropped = 0
for item in data:
if dropped >= drop:
yield item
continue
if condition(item):
dropped += 1
continue
yield item
data = [1, 10, 2, 9, 3, 8, 4, 7]
out = list(iter_drop_n(data, lambda x: x < 5, 3))
这不需要额外的列表副本,只对列表迭代一次,并且只为每个项目调用一次条件。除非您真的想要查看整个列表,否则请停止对结果的list
调用,直接迭代返回的生成器。
发布于 2016-09-20 03:20:12
如果需要进行突变:
def do_remove(ls, N, predicate):
i, delete_count, l = 0, 0, len(ls)
while i < l and delete_count < N:
if predicate(ls[i]):
ls.pop(i) # remove item at i
delete_count, l = delete_count + 1, l - 1
else:
i += 1
return ls # for convenience
assert(do_remove(l, N, matchCondition) == [10, 9, 8, 4, 7])
https://stackoverflow.com/questions/39580063
复制相似问题