CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-collections-extended

Extra Python Collections - bags (multisets) and setlists (ordered sets)

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

setlists.mddocs/

Setlists and Ordered Sets

Setlists are ordered collections of unique elements that combine list-like indexing with set-like uniqueness constraints. They maintain insertion order while enforcing element uniqueness, providing efficient index-based access and set operations.

Capabilities

Setlist Construction

Create ordered sets from iterables with automatic duplicate removal.

class SetList:
    def __init__(self, iterable=None, raise_on_duplicate=False):
        """Create a setlist from an iterable.
        
        Args:
            iterable: Values to initialize the setlist with
            raise_on_duplicate: If True, raise ValueError on duplicate values
        """

def setlist(iterable=None, raise_on_duplicate=False):
    """Create a mutable setlist from an iterable."""

def frozensetlist(iterable=None, raise_on_duplicate=False):
    """Create an immutable, hashable setlist from an iterable."""

Usage examples:

from collections_extended import setlist, frozensetlist

# Create from string - duplicates removed, order preserved
sl = setlist('abracadabra')
print(sl)  # setlist(('a', 'b', 'r', 'c', 'd'))

# Raise error on duplicates
try:
    sl = setlist('hello', raise_on_duplicate=True)
except ValueError:
    print("Duplicate 'l' found")

# Create immutable setlist
fsl = frozensetlist([1, 2, 3, 2, 1])
print(len(fsl))  # 3

Sequence Operations

Access and query elements using list-like indexing and sequence operations.

def __getitem__(self, index):
    """Get element at index or slice.
    
    Args:
        index: int or slice object
        
    Returns:
        Element at index or new setlist for slices
    """

def index(self, value, start=0, end=None):
    """Return index of value between start and end.
    
    Args:
        value: Element to find
        start: Start index for search
        end: End index for search
        
    Returns:
        int: Index of the element
        
    Raises:
        ValueError: If value not found or outside start-end range
    """

def count(self, value):
    """Return count of value (always 0 or 1 for setlists).
    
    Args:
        value: Element to count
        
    Returns:
        int: 1 if value in setlist, 0 otherwise
    """

def sub_index(self, sub, start=0, end=None):
    """Return index of a subsequence.
    
    Args:
        sub: Sequence to search for
        start: Start index for search
        end: End index for search
        
    Returns:
        int: Index of first element of subsequence
        
    Raises:
        ValueError: If subsequence not found
    """

Usage examples:

sl = setlist('abcde')
print(sl[2])         # 'c'
print(sl[1:4])       # setlist(('b', 'c', 'd'))
print(sl.index('d')) # 3
print(sl.count('c')) # 1
print(sl.sub_index(['b', 'c']))  # 1

Mutable Setlist Operations

Modify setlist contents while maintaining uniqueness constraints.

def append(self, value):
    """Append value to the end.
    
    Args:
        value: Value to append
        
    Raises:
        ValueError: If value already in setlist
    """

def insert(self, index, value):
    """Insert value at index.
    
    Args:
        index: Position to insert at
        value: Value to insert
        
    Raises:
        ValueError: If value already in setlist
    """

def extend(self, values):
    """Append all values to the end.
    
    Args:
        values: Iterable of values to append
        
    Raises:
        ValueError: If any value already present or duplicates in values
    """

def remove(self, value):
    """Remove value from setlist.
    
    Args:
        value: Element to remove
        
    Raises:
        ValueError: If value not present
    """

def pop(self, index=-1):
    """Remove and return item at index.
    
    Args:
        index: Index to pop (default: last item)
        
    Returns:
        Any: The removed element
    """

def clear(self):
    """Remove all elements from setlist."""

def reverse(self):
    """Reverse the setlist in-place."""

def sort(self, *args, **kwargs):
    """Sort the setlist in-place."""

def swap(self, i, j):
    """Swap elements at indices i and j."""

Usage examples:

sl = setlist(['a', 'b', 'c'])
sl.append('d')         # setlist(['a', 'b', 'c', 'd'])
sl.insert(1, 'x')      # setlist(['a', 'x', 'b', 'c', 'd'])
sl.extend(['e', 'f'])  # setlist(['a', 'x', 'b', 'c', 'd', 'e', 'f'])

item = sl.pop()        # 'f', setlist now ['a', 'x', 'b', 'c', 'd', 'e']
sl.remove('x')         # setlist(['a', 'b', 'c', 'd', 'e'])
sl.reverse()           # setlist(['e', 'd', 'c', 'b', 'a'])

Set Operations

Mathematical set operations that preserve order based on the left operand.

def union(self, other):
    """Return union of setlists (all elements from both)."""

def intersection(self, other):
    """Return intersection of setlists (common elements)."""

def difference(self, other):
    """Return difference of setlists (elements in self but not other)."""

def symmetric_difference(self, other):
    """Return symmetric difference (elements in either but not both)."""

def __add__(self, other):
    """Concatenate setlists (other elements appended, duplicates raise error)."""

def __sub__(self, other):
    """Return difference of setlists."""

def __and__(self, other):
    """Return intersection of setlists."""

def __or__(self, other):
    """Return union of setlists."""

def __xor__(self, other):
    """Return symmetric difference of setlists."""

def issubset(self, other):
    """Check if all elements are in other."""

def issuperset(self, other):
    """Check if all elements of other are in self."""

Usage examples:

sl1 = setlist('abc')
sl2 = setlist('bcd')

print(sl1 | sl2)  # setlist(['a', 'b', 'c', 'd'])  (union)
print(sl1 & sl2)  # setlist(['b', 'c'])            (intersection)
print(sl1 - sl2)  # setlist(['a'])                 (difference)
print(sl1 ^ sl2)  # setlist(['a', 'd'])            (symmetric difference)

print(setlist('ab').issubset(sl1))  # True

Set-like Mutable Operations

Mutable set operations that modify the setlist in-place.

def add(self, item):
    """Add item if not already present (like set.add)."""

def update(self, values):
    """Add all values, ignoring duplicates (like set.update)."""

def discard(self, value):
    """Remove value if present, silent if missing (like set.discard)."""

def discard_all(self, elems_to_delete):
    """Remove all elements in elems_to_delete, ignoring missing."""

def remove_all(self, elems_to_delete):
    """Remove all elements in elems_to_delete.
    
    Raises:
        ValueError: If any element not present or duplicates in elems_to_delete
    """

def difference_update(self, other):
    """Remove all elements in other from self."""

def intersection_update(self, other):
    """Keep only elements also in other."""

def symmetric_difference_update(self, other):
    """Update to symmetric difference with other."""

Usage examples:

sl = setlist('abc')
sl.add('d')           # setlist(['a', 'b', 'c', 'd'])
sl.add('b')           # No change - 'b' already present
sl.update('efg')      # setlist(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
sl.discard('x')       # No error - 'x' not present
sl.discard_all('aei') # Removes 'a' and 'e', ignores 'i'

Sequence-like Mutable Operations

Additional list-like operations for fine-grained control.

def __setitem__(self, index, value):
    """Set element at index to value.
    
    Args:
        index: int or slice
        value: New value or sequence of values
        
    Raises:
        ValueError: If value already exists elsewhere in setlist
    """

def __delitem__(self, index):
    """Delete element at index or slice."""

def shuffle(self, random=None):
    """Shuffle elements in-place.
    
    Args:
        random: Random function (default: random.random)
    """

Usage examples:

sl = setlist(['a', 'b', 'c', 'd'])
sl[1] = 'x'           # setlist(['a', 'x', 'c', 'd'])
del sl[0]             # setlist(['x', 'c', 'd'])
sl.shuffle()          # Random order, e.g., setlist(['d', 'x', 'c'])

Immutable Setlists

Create hashable, immutable versions for use as dictionary keys or set elements.

class frozensetlist(SetList, Hashable):
    def __hash__(self):
        """Return hash value for the frozensetlist."""

Usage examples:

from collections_extended import frozensetlist

# Immutable setlists can be dict keys
fsl1 = frozensetlist('abc')
fsl2 = frozensetlist('def')
mapping = {fsl1: 'first', fsl2: 'second'}

# Or in sets
setlist_set = {frozensetlist('hello'), frozensetlist('world')}

Copy and Comparison

Create copies and compare setlists efficiently.

def copy(self):
    """Return a shallow copy of the setlist."""

def __eq__(self, other):
    """Check equality with another setlist (order matters)."""

def __ne__(self, other):
    """Check inequality with another setlist."""

Install with Tessl CLI

npx tessl i tessl/pypi-collections-extended

docs

bags.md

bijections.md

index.md

indexed-dicts.md

range-maps.md

setlists.md

tile.json