Created
August 25, 2013 04:39
-
-
Save mxml-barmstrong/6332032 to your computer and use it in GitHub Desktop.
Python Index, IndexBag, Multidex
This file contains hidden or 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
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>} |
This file contains hidden or 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
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