Ответ 1
thelist[:] = [d for d in thelist if d.get('id') != 2]
Изменить: поскольку некоторые сомнения были высказаны в комментарии о производительности этого кода (некоторые из них основаны на непонимании характеристик производительности Python, некоторые из которых предполагают, что за пределами указанных спецификаций существует ровно один dict в список со значением 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 или лучше, конечно) - но этот код ломается, если число dicts, удовлетворяющих условию удаления, не точно один. Обобщая это, мы имеем:
$ 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
где перетасовка может быть удалена, поскольку, как мы знаем, уже существует три равных dicts для удаления. И 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 микросекунд в более крупный;-). Избегание или критика простых, простых и безупречно эффективных решений (например, понимание списков для этого общего класса "удалить некоторые элементы из списка" ) - особенно неприятный пример известного принципа Кнут и Хоар: "преждевременная оптимизация корень всего зла в программировании"! -)