Как инвертировать словарь без использования дополнительной памяти?

Пишу критичное по памяти и производительности приложение. Для некоторых повторящихся вычислений задекорировал функции с использованием техники memoization. Крупные неоднократно повторяющиеся объекты храню в таком кеше:
from collections import defaultdict
from itertools import count
cache = defaultdict(count().next)
Таким образом, каждый добавлемый в кеш объект получает уникальный последовательный индекс, т.е. в словаре уникальны не только ключи, но и значения. После окончания вычислений требуется восстановить объекты из кеша по индексу, для чего нужно инвертировать словарь. Он занимает сотни мегабайт, поэтому я ищу способ такого инвертирования cache -> xcache, которое не удваивало бы объём данных в памяти. Я хочу удалять элемент из одного словаря и сразу добавлять в другой, чтобы данные плавно "перетекли". Другими словами, в памяти не должны одновременно находиться два словаря с полным набором ключей и значений в каждом. Основная возникающая проблема - итерация по изменяющемуся словарю. Как это правильно реализовать?
  • Вопрос задан
  • 895 просмотров
Решения вопроса 2
> Он занимает сотни мегабайт
вы имеете в виду что данные хранящиеся в словаре занимают сотни мегабайт, или сам объект словаря занимает сотни мегабайт?

Поскольку от того, что вы инвертируете словарь, копий ключей и значений в памяти не появится, увлечение памяти будет только на саму структуру нового словаря.
Ответ написан
adugin
@adugin Автор вопроса, куратор тега Python
Пока додумался до такого метода:
xcache = dict()
while cache:
    	key, val = cache.iteritems().next()
    	xcache[cache.pop(key)] = key
Такой способ в 3 раза величивает время исполнения скрипта (с 60 до 180 секунд на моём ноутбуке) по сравнению с традиционным методом инвертирования "в лоб". Есть ли способ лучше?

Update #1: Тоже тормозит.
xcache = dict()
cpop = cache.pop
while cache:
    key = cache.iterkeys().next()
    xcache[cpop(key)] = key
del cache

Update #2: Вот так скорость вернулась на значение 60 секунд. Что ещё?
xcache = dict()
cpop = cache.popitem
while cache:
    key, val = cpop()
    xcache[val] = key
del cache
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы