setutils - IndexedSet type

The set type brings the practical expressiveness of set theory to Python. It has a very rich API overall, but lacks a couple of fundamental features. For one, sets are not ordered. On top of this, sets are not indexable, i.e, my_set[8] will raise an TypeError. The IndexedSet type remedies both of these issues without compromising on the excellent complexity characteristics of Python’s built-in set implementation.

class boltons.setutils.IndexedSet(other=None)[source]

IndexedSet is a collections.MutableSet that maintains insertion order and uniqueness of inserted elements. It’s a hybrid type, mostly like an OrderedSet, but also list-like, in that it supports indexing and slicing.

Parameters:other (iterable) – An optional iterable used to initialize the set.
>>> x = IndexedSet(list(range(4)) + list(range(8)))
>>> x
IndexedSet([0, 1, 2, 3, 4, 5, 6, 7])
>>> x - set(range(2))
IndexedSet([2, 3, 4, 5, 6, 7])
>>> x[-1]
7
>>> fcr = IndexedSet('freecreditreport.com')
>>> ''.join(fcr[:fcr.index('.')])
'frecditpo'

Standard set operators and interoperation with set are all supported:

>>> fcr & set('cash4gold.com')
IndexedSet(['c', 'd', 'o', '.', 'm'])

As you can see, the IndexedSet is almost like a UniqueList, retaining only one copy of a given value, in the order it was first added. For the curious, the reason why IndexedSet does not support setting items based on index (i.e, __setitem__()), consider the following dilemma:

my_indexed_set = [A, B, C, D]
my_indexed_set[2] = A

At this point, a set requires only one A, but a list would overwrite C. Overwriting C would change the length of the list, meaning that my_indexed_set[2] would not be A, as expected with a list, but rather D. So, no __setitem__().

Otherwise, the API strives to be as complete a union of the list and set APIs as possible.

add(item) → add item to the set[source]
clear() → empty the set[source]
count(val) -> count number of instances of value (0 or 1)[source]
difference(*others) → get a new set with elements not in others[source]
difference_update(*others) -> discard self.intersection(*others)[source]
discard(item) -> discard item from the set (does not raise)[source]
classmethod from_iterable(it) → create a set from an iterable[source]
index(val) → get the index of a value, raises if not present[source]
intersection(*others) → get a set with overlap of this and others[source]
intersection_update(*others) -> discard self.difference(*others)[source]
isdisjoint(other) → return True if no overlap with other[source]
issubset(other) → return True if other contains this set[source]
issuperset(other) → return True if set contains other[source]
iter_difference(*others) → iterate over elements not in others[source]
iter_intersection(*others) → iterate over elements also in others[source]
iter_slice(start, stop, step=None)[source]

iterate over a slice of the set

pop(index) -> remove the item at a given index (-1 by default)[source]
remove(item) → remove item from the set, raises if not present[source]
reverse() → reverse the contents of the set in-place[source]
sort() → sort the contents of the set in-place[source]
symmetric_difference(*others) → XOR set of this and others[source]
symmetric_difference_update(other) → in-place XOR with other[source]
union(*others) → return a new set containing this set and others[source]
update(*others) → add values from one or more iterables[source]