From 1de6b0a497416c9bcfebc23bde68b2346b3c217b Mon Sep 17 00:00:00 2001 From: Mahmoud Hashemi Date: Wed, 13 Mar 2013 04:23:09 -0700 Subject: [PATCH] add slicing support and .clear() --- boltons/setutils.py | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/boltons/setutils.py b/boltons/setutils.py index 5bf39b9..99c427c 100644 --- a/boltons/setutils.py +++ b/boltons/setutils.py @@ -1,14 +1,13 @@ # -*- coding: utf-8 -*- from bisect import insort, bisect -from itertools import chain +from itertools import chain, islice from collections import MutableSet _MISSING = object() +_COMPACTION_FACTOR = 10 -# TODO: slicing # TODO: better exception messages -# TODO: clear() # TODO: inherit from set() # TODO: raise exception on non-set params? # TODO: technically reverse operators should probably reverse the @@ -57,7 +56,7 @@ class IndexedSet(MutableSet): if not self.item_index_map: del self.dead_indices[:] del self.item_list[:] - elif len(ded) > 8 and len(ded) > len(items) / 10: + elif len(ded) > 8 and len(ded) > len(items) / _COMPACTION_FACTOR: self._compact() elif ded[-1] == len(items) - 1: # get rid of dead right hand side num_dead = 1 @@ -108,6 +107,11 @@ class IndexedSet(MutableSet): except KeyError: pass + def clear(self): + del self.item_list[:] + del self.dead_indices[:] + self.item_index_map.clear() + def add(self, item): if item not in self.item_index_map: self.item_index_map[item] = len(self.item_list) @@ -192,12 +196,14 @@ class IndexedSet(MutableSet): self.discard(val) def difference_update(self, *others): - # if self in others: clear() + if self in others: + self.clear() for val in self.intersection(*others): self.discard(val) def symmetric_difference_update(self, other): # note singular 'other' - # if self is other: clear() + if self is other: + self.clear() for val in other: if val in self: self.discard(val) @@ -220,8 +226,26 @@ class IndexedSet(MutableSet): self.symmetric_difference_update(*others) return self + def iter_slice(self, start, stop, step=None): + iterable = self + if start is not None: + start = start + bisect(self.dead_indices, start) + if stop is not None: + stop = stop + bisect(self.dead_indices, stop) + if step is not None and step < 0: + step = -step + iterable = reversed(self) + return islice(iterable, start, stop, step) + #list operations - def __getitem__(self, index): # TODO: support slicing + def __getitem__(self, index): + try: + start, stop, step = index.start, index.stop, index.step + except AttributeError: + pass + else: + iter_slice = self.iter_slice(start, stop, step) + return self.from_iterable(iter_slice) if index < 0: index += len(self) skip = bisect(self.dead_indices, index) @@ -277,6 +301,7 @@ if __name__ == '__main__': x |= set([10]) print zero2nine, five2nine, x, x[-1] print zero2nine ^ five2nine + print x[:3], x[2:4:-1] try: hundo = IndexedSet(xrange(1000))