Python: как разбить словарь на основе значений его ключей?

Скажем, у меня есть словарь, построенный следующим образом:

d={0:1, 1:2, 2:3, 10:4, 11:5, 12:6, 100:7, 101:8, 102:9, 200:10, 201:11, 202:12}

и я хочу создать подсловарь d1, нарезав d таким образом, чтобы d1 содержал следующие ключи: 0, 1, 2, 100, 101, 102. Окончательный вывод должен быть:

d1={0:1, 1:2, 2:3, 100:7, 101:8, 102:9}

Есть ли эффективный Pythonic-способ сделать это, учитывая, что мой реальный словарь содержит более 2 000 000 элементов?

Я думаю, что этот вопрос относится ко всем случаям, когда ключи являются целыми числами, когда срезы должны следовать определенным правилам неравенства и когда конечным результатом должен быть набор срезов, объединенных в одном словаре.


person FaCoffee    schedule 05.11.2016    source источник
comment
Откуда берутся эти правила? Что должно произойти, если эти ключи не имеют значений? Думали ли вы о понимании словаря {k: d[k] for k in [0, 1, ...]}?   -  person jonrsharpe    schedule 05.11.2016
comment
В моем случае все ключи имеют значения.   -  person FaCoffee    schedule 05.11.2016
comment
Вы не можете нарезать словарь, так как это изменяемое отображение, а не последовательность. Я думаю, что понимание dict - ваш лучший выбор.   -  person flybonzai    schedule 05.11.2016
comment
Нарезка словаря по своей сути не является невозможной; Python просто не предоставляет синтаксис для этого, как, скажем, Perl (хотя в Perl вы просто возвращаете соответствующие значения, а не подмножество хэша).   -  person chepner    schedule 05.11.2016


Ответы (2)


Вы можете использовать понимание словаря с:

d = {0:1, 1:2, 2:3, 10:4, 11:5, 12:6, 100:7, 101:8, 102:9, 200:10, 201:11, 202:12}
keys = (0, 1, 2, 100, 101, 102)
d1 = {k: d[k] for k in keys}

В python 2.7 вы также можете вычислять ключи с помощью (в python 3.x замените it.ifilter(...) на filter(...)):

import itertools as it

d = {0:1, 1:2, 2:3, 10:4, 11:5, 12:6, 100:7, 101:8, 102:9, 200:10, 201:11, 202:12}
d1 = {k: d[k] for k in it.ifilter(lambda x: 1 < x <= 11, d.keys())}
person Olivier Pellier-Cuit    schedule 05.11.2016
comment
Ну, я должен был указать это в первую очередь. Хотя это правда, что я знаю, какие нужны ключи, их слишком много, чтобы явно помещать их в кортеж. Есть ли способ построить кортеж, используя правила неравенства? - person FaCoffee; 05.11.2016
comment
@ CF84: Каково ваше определение правила неравенства? Пожалуйста, поделитесь полной информацией, мы не можем читать ваши мысли :) - person Anonymous; 05.11.2016
comment
Одним из определений может быть составление всех значений, ключи которых больше и меньше определенного значения x. Пример: 06010001 < x <= 06012000. - person FaCoffee; 05.11.2016
comment
см. мой обновленный ответ. С python 3.x вам просто нужно заменить it.filter(...) на filter(...) - person Olivier Pellier-Cuit; 05.11.2016

Одним из кратких способов создания подсловаря является использование operator.itemgetter. Эта функция принимает несколько аргументов и возвращает новую функцию для возврата кортежа, содержащего соответствующие элементы данной итерации.

from operator import itemgetter as ig

k = [0, 1, 2, 100, 101, 102]
# ig(0,1,2,100,101,102) == lambda d : (d[0], d[1], d[2], d[100], d[101], d[102])
d1 = dict(zip(k, ig(*k)(d)))
person chepner    schedule 05.11.2016