Самый быстрый способ удаления определенных ключей из dict в Python - PullRequest
7 голосов
/ 20 июня 2010

Я ищу самый быстрый / эффективный способ удаления определенных ключей в python dict

Вот несколько вариантов

for k in somedict.keys(): 
    if k.startswith("someprefix"): 
        del somedict[k]

или

dict((k, v) for (k, v) in somedict.iteritems() if not k.startswith('someprefix'))

По логике первый фрагмент должен быть быстрее для небольших диктовок, он не создает копию диктата, а создает список всех ключей, однако двойной поиск и восстановление диктов требует много времени. В то время как второй быстрее на больших диктовках, но требует в 2 раза больше памяти. Я проверил свое предположение в небольшом тесте.

Что-нибудь быстрее?

Ответы [ 2 ]

12 голосов
/ 20 июня 2010

Не только del более легко понять, но кажется немного быстрее, чем pop () :

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "for k in d.keys():" "  if k.startswith('f'):" "    del d[k]"
1000000 loops, best of 3: 0.733 usec per loop

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "for k in d.keys():" "  if k.startswith('f'):" "    d.pop(k)"
1000000 loops, best of 3: 0.742 usec per loop

Редактировать: спасибо Алексу Мартелли за предоставление инструкций о том, как выполнить этот сравнительный анализ. Надеюсь, я никуда не соскользнул.

Сначала измерьте время, необходимое для копирования:

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "d1 = d.copy()"
1000000 loops, best of 3: 0.278 usec per loop

Эталон на копируемом дикте:

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "d1 = d.copy()" "for k in d1.keys():" "  if k.startswith('f'):" "    del d1[k]"
100000 loops, best of 3: 1.95 usec per loop

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "d1 = d.copy()" "for k in d1.keys():" "  if k.startswith('f'):" "    d1.pop(k)"
100000 loops, best of 3: 2.15 usec per loop

Вычитая стоимость копирования, мы получаем 1,872 у.е. для pop() и 1,672 для del.

9 голосов
/ 20 июня 2010

Если диктат достаточно велик, вместо него может иметь смысл сгенерировать совершенно новый диктат.

dict((k, v) for (k, v) in somedict.iteritems() if not k.startswith('someprefix'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...