Slicing

A wc_rules.indexer.Slicer object is essentially a set defined as a boolean-valued dictionary. The keys may be literals or namedtuples.

A positive slicer (psl) defines a set by inclusion, i.e., it maps elements contained in the set to True values (returns False for all other values). To create a positive slicer, use Slicer() or Slicer(default=False).

A negative slicer (nsl) defines a set by exclusion, i.e., it maps elements not contained in the set to False values (returns True for all other values). To create a negative slicer, use Slicer(default=True).


In [1]:
from wc_rules.indexer import Slicer

In [2]:
# A positive slicer
S = Slicer(default=False).add_keys(['a','b'])

In [3]:
# Checking for included elements
S['a']


Out[3]:
True

In [4]:
# Checking for excluded elements
S['c']


Out[4]:
False

In [5]:
# A negative slicer
S = Slicer(default=True).add_keys(['c'])

In [6]:
# Checking for included elements
S['a']


Out[6]:
True

In [7]:
# Checking for excluded elements
S['c']


Out[7]:
False

Slicers can be combined key-wise using Boolean operators ~, & and | denoting NOT, AND and OR respectively.

Boolean NOT

Since a positive slicer denotes the elements included in a set, its inversion ~ is a negative slicer that denotes the elements excluded from the set, i.e., its complement.


In [8]:
# inverting a positive slicer
S = Slicer(default=False).add_keys(['a','b'])
T = ~S
T.default,T['a'],T['b'],T['c']


Out[8]:
(True, False, False, True)

Similarly, the inversion of a negative slicer is a positive slicer.


In [9]:
# inverting a negative slicer
S = Slicer(default=True).add_keys(['a','b'])
T = ~S
T.default,T['a'],T['b'],T['c']


Out[9]:
(False, True, True, False)

Boolean AND

The Boolean AND returns True for all values that both slicers return True. When mixing positive and negative slicers using AND, deMorgan's laws are followed.


In [10]:
# psl(A) & psl(B) = psl(intersection(A,B))
A = Slicer().add_keys(['a','b'])
B = Slicer().add_keys(['b','c'])
C = A & B
C.default, C['a'],C['b'],C['c']


Out[10]:
(False, False, True, False)

In [11]:
# psl(A) & nsl(B) = psl(A - intersection(A,B))
A = Slicer().add_keys(['a','b'])
Bp = Slicer(default=True).add_keys(['b','c'])
C = A & Bp
C.default, C['a'],C['b'],C['c']


Out[11]:
(False, True, False, False)

In [12]:
# Similarly, nsl(A) & psl(B) = psl(B - intersection(A,B))
Ap = Slicer(default=True).add_keys(['a','b'])
B = Slicer().add_keys(['b','c'])
C = Ap & B
C.default, C['a'],C['b'],C['c']


Out[12]:
(False, False, False, True)

In [13]:
# nsl(A) & nsl(B) = nsl(union(A,B))
Ap = Slicer(default=True).add_keys(['a','b'])
Bp = Slicer(default=True).add_keys(['b','c'])
C = Ap & Bp
C.default, C['a'],C['b'],C['c']


Out[13]:
(True, False, False, False)

Boolean OR

The Boolean OR returns True for all values that either slicer returns True. When mixing positive and negative slicers using OR, deMorgan's laws are followed.


In [14]:
# psl(A) | psl(B) = psl(union(A,B))
A = Slicer().add_keys(['a','b'])
B = Slicer().add_keys(['b','c'])
C = A | B
C.default, C['a'],C['b'],C['c']


Out[14]:
(False, True, True, True)

In [15]:
# psl(A) | nsl(B) = nsl(B - intersection(A,B))
A = Slicer().add_keys(['a','b'])
Bp = Slicer(default=True).add_keys(['b','c'])
C = A | Bp
C.default, C['a'],C['b'],C['c']


Out[15]:
(True, True, True, False)

In [16]:
# Similarly, nsl(A) | psl(B) = nsl(A - intersection(A,B))
Ap = Slicer(default=True).add_keys(['a','b'])
B = Slicer().add_keys(['b','c'])
C = Ap | B
C.default, C['a'],C['b'],C['c']


Out[16]:
(True, False, True, True)

In [17]:
# nsl(A) | nsl(B) = nsl(intersection(A,B))
Ap = Slicer(default=True).add_keys(['a','b'])
Bp = Slicer(default=True).add_keys(['b','c'])
C = Ap | Bp
C.default, C['a'],C['b'],C['c']


Out[17]:
(True, True, False, True)