Как стать автором
Обновить

Комментарии 25

Может имеет смысл добавить режим, в котором проверяется наличие коллизии между ключами начального/прямого и обратного словаря? Например, можно выбрасывать исключение в таком случае. И добавить проверку, что все значения прямого словаря уникальные. И также выбрасывать исключение в случае обнаружения дубликатов.

кстати да, спасибо, не подумал об этом. Хотя может список отдавать значений, чтобы потом выбрать можно было. но тогда не понятно будет что ожидать, или значение или список, проверки дополнительные со значение проводить. Есть еще над чем подумать

Например, в одной системе тип документа "Договор", а в другой "Contract".

одна система принимает буквенный код валюты "RUB", а другая числовой "643"

А что вы будете делать, когда систем станет три?

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

160 элементов - это всё ещё "мало". Были бы сотни тысяч, можно было бы подумать об эффективном хранении и из-за этого - об эффективном доступе. А тут...

Отдельный минус подхода - смешивание ключей туда-обратно. В языке со слабой типизацией можно накосячить с лёгкостью необычайной. Лучше соблюдать чистоту рук, однако!

Но кстати, быстрое-и-грязное решение - это напихать ключи в один словарь

def make_bimap(src):  # src - dict
    dst = {}
    dst.update(src)
    dst.update((v, k) for (k, v) in src.items())
    return dst

Но при этом надо удостовериться, что нет конфликта ключей в обратном направлении.

Ну и не забываем про наследие предков. Бимапы люди делали издревле, и быстрый поиск даёт, например, PyPy.bidict.

я наверное не знал что это бимап называтся, того и не нашел нечего))). Но все ровно было интересно по изобретать

В современных питонах можно проще

a = {"one": 1, "two": 2}
bi = {**a, **{v:k for k, v in a.items()}}
bi
{'one': 1, 'two': 2, 1: 'one', 2: 'two'}

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

assert digit_mapping['two'] == 2
assert digit_mapping[2] == 'two'
assert digit_mapping['2'] == 'two'

Как бы не получился комикс "брошу яваскрипт и стану проституткой". С вот этим вот преобразованием чисел в строки (или строк в числа). Потому что тут рядом тусуются проблемы локалей.

Так-то каждый может. А вот сделайте такую мапу, у которой спрашиваешь про новый договор: m.get("договор №18"), а она возвращает: "составлен, одобрен, подписан и уже завершён, деньги уже на вашем счету". Вот это я понимаю.

Скорее всего, что подход "би"-маппинга стоит решать на уровне получения объектов из БД. Это работает, если возможно контролировать БД всех систем.

В остальных случаях идея может быть улучшена, если известна система "источник" и система "назначение", а они известны в текущем примере, поскольку в этом случае маппинг выполняется с помощью только одного словаря "sourse: destination" и исключено появление каких-либо ошибок по ключам, о которых писали предыдущие комментаторы.

PS. Код не работает, если values вmapping: dict не hashable. А на __init__ это не проверяется.

не создастся класс тогда, ошибка словаря зарайзиртся

Верно. Но этот Exception в коде никак не обрабатывается. Я это имел ввиду под "не работает".

Был бы такой объект в python, в котором происходит маппинг не зависимо
от передаваемого ключа. Передаешь RUB получаешь 643, передаешь 643
получаешь RUB

Он есть.
from enum import Enum
class Currencies(Enum):

RUB = 840

Currencies['RUB']
Out[8]: <_Currencies.RUB: 840>

Currencies(840)
Out[10]: <_Currencies.RUB: 840>

Прикольно, не знал что он так работает. А он значения отдаст тоже как хэш-таблица? Почитал исходники, не совсем понял как он работает. По сути то что мне и нужно, но если бы я знал, не придумал бы сам такой велосипед))). У Enum по разному надо вызывать метод чтобы получить значения (Currencies['RUB'], Currencies(840)) а меня однообразно (может это преимущество или недостаток)))

assert digit_mapping['two'] == 2
assert digit_mapping[2] == 'two'
assert digit_mapping['2'] == 'two'

Не уверен, что правильно понял Ваш вопрос, но хранит енам данные в дикте, да.

from enum import Enum
class Currencies(Enum):
    RUB = 840

Currencies.__members__
Out[6]: mappingproxy({'RUB': <Currencies.RUB: 840>})
rub = Currencies.__members__['RUB']
rub.value
Out[8]: 840
rub.name
Out[9]: 'RUB'

не совсем понял как он работает


Загляните в: Currencies.__dict__, там статичесикие аттрибуты на каждый элемент и две мапы прямая и обратная.

Скажите а как сделать так, чтобы f(a, b)=c где с линейная зависимость от некой функции в которую входят а и b!? То есть а и b подставляем в словарь и он выдает с который монотонно возрастает от а и b и линейный сам по себе!?

Извините, я не понял вопроса. Попробуйте переформулировать

Кажется, что вопрос не по теме поста. Как это соотносится с бимапами?

И, собственно, в чём проблема? В мемоизации функции f? Зачем нужен словарь, на что должна влиять монотонность и, тем более, линейность? Какой прикладной смысл этого всего?

тогда придется все методы словаря описывать, ну в принципе можно, спасибо

Идея этого абстрактного класса в том, что нужно только небольшую часть методов реализовывать. Остальное работает на этой базе.

__getitem__
__len__
__iter__



прикольно, но надо будет тогда все до ума довести, а то найдут не стандартные случаии

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории