thelist[:] = [d for d in thelist if d.get('id') != 2]
Редактировать : поскольку некоторые комментарии были высказаны в комментарии по поводу производительности этого кода (некоторые основаны на неправильном понимании характеристик производительности Python, другие на предположении, помимо указанных спецификаций, что в список со значением 2 для ключа 'id'), я хотел бы предложить заверение на этот счет.
На старой Linux-системе, измеряя этот код:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(99)]; import random" "thelist=list(lod); random.shuffle(thelist); thelist[:] = [d for d in thelist if d.get('id') != 2]"
10000 loops, best of 3: 82.3 usec per loop
из которых около 57 микросекунд для random.shuffle (необходимо, чтобы гарантировать, что удаляемый элемент не ВСЕГДА в одном месте ;-) и 0,65 микросекунд для начальной копии (кто бы ни беспокоился о влиянии на производительность мелких копий Python) списки наиболее очевидно на обед ;-), необходимо, чтобы избежать изменения исходного списка в цикле (таким образом, у каждого участка цикла есть, что удалить; -).
Когда известно, что нужно удалить только один элемент, его можно найти и удалить еще быстрее:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(99)]; import random" "thelist=list(lod); random.shuffle(thelist); where=(i for i,d in enumerate(thelist) if d.get('id')==2).next(); del thelist[where]"
10000 loops, best of 3: 72.8 usec per loop
(конечно, используйте встроенный next
вместо .next
, если вы используете Python 2.6 или выше), но этот код не работает, если число диктовок, которые удовлетворяют условию удаления, не совсем точно один. Обобщая это, мы имеем:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*3; import random" "thelist=list(lod); where=[i for i,d in enumerate(thelist) if d.get('id')==2]; where.reverse()" "for i in where: del thelist[i]"
10000 loops, best of 3: 23.7 usec per loop
где перетасовка может быть удалена, потому что, как мы знаем, уже есть три равноудаленных диктовки для удаления. И listcomp, без изменений, хорошо обходится:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*3; import random" "thelist=list(lod); thelist[:] = [d for d in thelist if d.get('id') != 2]"
10000 loops, best of 3: 23.8 usec per loop
полностью шея и шея, при этом нужно удалить только 3 элемента из 99. С более длинными списками и большим количеством повторений, это, конечно, еще больше:
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*133; import random" "thelist=list(lod); where=[i for i,d in enumerate(thelist) if d.get('id')==2]; where.reverse()" "for i in where: del thelist[i]"
1000 loops, best of 3: 1.11 msec per loop
$ python -mtimeit -s"lod=[{'id':i, 'name':'nam%s'%i} for i in range(33)]*133; import random" "thelist=list(lod); thelist[:] = [d for d in thelist if d.get('id') != 2]"
1000 loops, best of 3: 998 usec per loop
В общем, очевидно, что не стоит использовать тонкость создания и обращения списка индексов для удаления, в отличие от совершенно простого и очевидного понимания списка, чтобы, возможно, получить 100 наносекунд в одном небольшом случае - и потерять 113 микросекунд в больше ;-). Избежание или критика простых, простых и совершенно адекватных производительности решений (таких как составление списков для этого общего класса проблем «удалить некоторые элементы из списка») является особенно неприятным примером известного тезиса Кнута и Хоара о том, что «преждевременная оптимизация - это корень зла в программировании "! -)