Это продолжение аналогичного вопроса , в котором был задан наилучший способ написания
for item in somelist:
if determine(item):
code_to_remove_item
, и, похоже, консенсус был достигнут относительно чего-то вроде
somelist[:] = [x for x in somelist if not determine(x)]
Тем не менее, я думаю, что если вы удаляете только несколько элементов, большинство элементов копируются в один и тот же объект, и, возможно, это происходит медленно.В ответе на другой связанный вопрос кто-то предлагает:
for item in reversed(somelist):
if determine(item):
somelist.remove(item)
Однако здесь list.remove
будет искать элемент, который является O (N) в длине списка.Возможно, мы ограничены в том, что список представлен в виде массива, а не связанного списка, поэтому при удалении элементов нужно будет перемещать все после него.Тем не менее, здесь предлагается представить коллекцию в виде двусвязного списка.Затем должно быть возможно удалить в O (1) во время итерации.Как бы мы на самом деле достигли этого?
Обновление : я также провел некоторое время тестирование со следующим кодом:
import timeit
setup = """
import random
random.seed(1)
b = [(random.random(),random.random()) for i in xrange(1000)]
c = []
def tokeep(x):
return (x[1]>.45) and (x[1]<.5)
"""
listcomp = """
c[:] = [x for x in b if tokeep(x)]
"""
filt = """
c = filter(tokeep, b)
"""
print "list comp = ", timeit.timeit(listcomp,setup, number = 10000)
print "filtering = ", timeit.timeit(filt,setup, number = 10000)
и получил:
list comp = 4.01255393028
filtering = 3.59962391853