Created
August 12, 2017 23:35
-
-
Save Nazek42/87971a526ec045ba1e79cea99797746b to your computer and use it in GitHub Desktop.
Python two-way dictionary
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# dedict, aka "double-ended dict" | |
# A data structure allowing for bidirectional lookups | |
# | |
# Syntax for lookups: | |
# By key: | |
# myDedict[key] OR myDedict[key:] | |
# By value: | |
# myDedict[:value] | |
# This is meant to evoke the dict literal syntax of key: value. | |
# | |
# Assignment works similarly: | |
# myDedict[key] = value | |
# myDedict[key:] = value | |
# myDedict[:value] = key | |
# | |
# The 'in' operator works as with a normal dict: | |
# key in myDedict | |
# | |
# The inversion operator (~) can be used to return a key-value swapped | |
# shallow copy of the dedict: | |
# myInvDedict = ~myDedict | |
# | |
# This can be used in conjuction with the 'in' operator: | |
# value in ~myDedict | |
# (equivalent to `value in myDedict.values()`) | |
class dedict: | |
def __init__(self, *args, **kwargs): | |
self._dict = dict(*args, **kwargs) | |
self._update_rdict() | |
def get_by_key(self, key): | |
return self._dict[key] | |
def get_by_value(self, value): | |
return self._rdict[value] | |
def set(self, key, value): | |
self[key] = value | |
def update(self, addition): | |
self._dict.update(addition) | |
self._update_rdict() | |
def keys(self): | |
return self._dict.keys() | |
def values(self): | |
return self._dict.values() | |
def items(self): | |
return self._dict.items() | |
def _update_dict(self): | |
self._dict = dict(zip(self._rdict.values(), self._rdict.keys())) | |
def _update_rdict(self): | |
self._rdict = dict(zip(self._dict.values(), self._dict.keys())) | |
def __len__(self): | |
return len(self._dict) | |
def __getitem__(self, key): | |
if isinstance(key, slice): | |
if key.start is None and key.step is None: # aka, if searching by value: | |
return self._rdict[key.stop] | |
elif key.stop is None and key.step is None: # aka, if searching by key: | |
return self._dict[key.start] | |
else: # malformed slice | |
raise TypeError("Malformed slice '{}'".format(key)) | |
else: # obey default lookup behavior | |
return self._dict[key] | |
def __setitem__(self, key, value): | |
if isinstance(key, slice): | |
if key.start is None and key.step is None: # aka, if setting by value: | |
self._rdict[key.stop] = value | |
self._update_dict() | |
elif key.stop is None and key.step is None: # aka, if setting by key: | |
self._dict[key.start] = value | |
self._update_rdict() | |
else: # malformed slice | |
raise TypeError("Malformed slice '{}'".format(key)) | |
else: # obey default lookup behavior | |
self._dict[key] = value | |
self._update_rdict() | |
def __delitem__(self, key): | |
if isinstance(key, slice): | |
if key.start is None and key.step is None: # aka, if searching by value: | |
del self._rdict[key.stop] | |
self._update_dict() | |
elif key.stop is None and key.step is None: # aka, if searching by key: | |
del self._dict[key.start] | |
self._update_rdict() | |
else: # malformed slice | |
raise TypeError("Malformed slice '{}'".format(key)) | |
else: # obey default lookup behavior | |
del self._dict[key] | |
self._update_rdict() | |
def __iter__(self): | |
return self._dict.__iter__() | |
def __contains__(self, key): | |
return (key in self._dict) | |
def __invert__(self): | |
return dedict(self._rdict) | |
def __repr__(self): | |
return "dedict({})".format(self._dict) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment