fork download
  1. from collections import defaultdict
  2.  
  3. class IndexedSet:
  4. def __init__(self):
  5. self._elements = set()
  6. self._indices = set()
  7.  
  8. def add(self, element):
  9. self._elements.add(element)
  10. for index in self._indices:
  11. index.add(element)
  12.  
  13. def remove(self, element):
  14. self._elements.remove(element)
  15. for index in self._indices:
  16. index.remove(element)
  17.  
  18. def index(self, key):
  19. index = Index(key)
  20. for element in self._elements:
  21. index.add(element)
  22. self._indices.add(index)
  23. return index
  24.  
  25. class Index:
  26. def __init__(self, key):
  27. self._key = key
  28. self._elements = defaultdict(set)
  29.  
  30. def add(self, element):
  31. self._elements[self._key(element)].add(element)
  32.  
  33. def remove(self, element):
  34. self._elements[self._key(element)].remove(element)
  35. if len(self._elements[self._key(element)]) == 0:
  36. del self._elements[self._key(element)]
  37.  
  38. def find(self, key):
  39. return self._elements[key]
  40.  
  41. # example:
  42. from operator import attrgetter
  43.  
  44. class User:
  45. def __init__(self, id, email_address, password_hash):
  46. self.id = id
  47. self.email_address = email_address
  48. self.password_hash = password_hash
  49.  
  50. @property
  51. def _tuple(self):
  52. return self.id, self.email_address, self.password_hash
  53.  
  54. def __eq__(self, other):
  55. return isinstance(other, User) and self._tuple == other._tuple
  56.  
  57. def __hash__(self):
  58. return hash(self._tuple)
  59.  
  60. users = IndexedSet()
  61. id_index = users.index(attrgetter('id'))
  62. email_address_index = users.index(attrgetter('email_address'))
  63. users.add(User(1, 'rightfold@gmail.com', b'abcd'))
  64. users.add(User(2, 'henk@example.com', b'defg'))
  65. print(id_index.find(1))
  66. print(id_index.find(2))
  67. print(id_index.find(3))
  68. print(email_address_index.find('rightfold@gmail.com'))
  69. print(email_address_index.find('henk@example.com'))
  70. print(email_address_index.find('foo@bar.baz'))
Success #stdin #stdout 0.03s 9008KB
stdin
Standard input is empty
stdout
{<__main__.User object at 0xb7470aec>}
{<__main__.User object at 0xb7470b2c>}
set()
{<__main__.User object at 0xb7470aec>}
{<__main__.User object at 0xb7470b2c>}
set()