Skip to content

Instantly share code, notes, and snippets.

@mxml-barmstrong
Created August 25, 2013 04:39
Show Gist options
  • Save mxml-barmstrong/6332032 to your computer and use it in GitHub Desktop.
Save mxml-barmstrong/6332032 to your computer and use it in GitHub Desktop.
Python Index, IndexBag, Multidex
In [1]: import index
In [2]: i = index.Multidex(unique_keys=('pk',), common_keys=('name',))
In [3]: class Person(object):
def __init__(self, name):
global last_pk
self.pk = last_pk
last_pk += 1
self.name = name
...:
In [4]: last_pk = 1
In [5]: people = [Person('Alice'), Person('Bob'), Person('Christina'), Person('Christina')]
In [6]: i.merge(people)
In [7]: i.at('pk', 1)
Out[7]: <__main__.Person at 0x1017c2490>
In [8]: i.at('name', 'Christina')
Out[8]: {<__main__.Person at 0x1017c26d0>, <__main__.Person at 0x1017c2710>}
import collections
import operator
class IndexBase(object):
def __init__(self, key, initial=None):
if isinstance(key, basestring):
self.key = operator.attrgetter(key)
elif isinstance(key, int):
self.key = operator.itemgetter(key)
else:
raise ValueError('key must be a basestring or int.')
if initial:
self.merge(initial)
def merge(self, items):
raise NotImplementedError
def add(self, item):
self.merge([item])
def umerge(self, items):
raise NotImplementedError
def remove(self, item):
self.unmerge([item])
class Index(IndexBase, dict):
def __init__(self, *args, **kwargs):
super(Index, self).__init__(*args, **kwargs)
def merge(self, items):
for item in items:
self[self.key(item)] = item
def unmerge(self, items):
for item in items:
k = self.key(item)
if self.get(k) == item:
del self[k]
class IndexBag(IndexBase, collections.defaultdict):
def __init__(self, *args, **kwargs):
super(IndexBase, self).__init__(set)
super(IndexBag, self).__init__(*args, **kwargs)
def merge(self, items):
for item in items:
self[self.key(item)].add(item)
def unmerge(self, items):
for item in items:
try:
self[self.key(item)].remove(item)
except KeyError:
continue
class Multidex(object):
def __init__(self, unique_keys=None, common_keys=None, initial=None):
self._indicies = {}
unique_keys = unique_keys or []
common_keys = common_keys or []
for key in unique_keys:
self._indicies[key] = Index(key, initial=initial)
for key in common_keys:
self._indicies[key] = IndexBag(key, initial=initial)
def by_key(self, key):
return self._indicies[key]
def at(self, key, val):
return self.by_key(key)[val]
def merge(self, items):
for index in self._indicies.itervalues():
index.merge(items)
def unmerge(self, items):
for index in self._indices.itervalues():
index.unmerge(items)
def add(self, item):
self.merge([item])
def remove(self, item):
self.unmerge([item])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment