Extra Python Collections - bags (multisets) and setlists (ordered sets)
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Bags (also known as multisets) are collections that track element counts, allowing duplicates while maintaining count information. They support mathematical set operations with multiplicity, statistical operations on collections, and efficient counting operations.
Create bags from iterables with automatic element counting.
class Bag:
def __init__(self, iterable=None):
"""Create a new bag.
Args:
iterable: Iterable to populate the bag from. Each element will be
added however many times it appears.
"""
def bag(iterable=None):
"""Create a mutable bag from an iterable."""
def frozenbag(iterable=None):
"""Create an immutable, hashable bag from an iterable."""Usage examples:
from collections_extended import bag, frozenbag
# Create from string - counts each character
b = bag('abracadabra')
print(b) # bag(('a', 'a', 'a', 'a', 'a', 'b', 'b', 'r', 'r', 'c', 'd'))
# Create from list
b = bag([1, 2, 2, 3, 3, 3])
print(b.count(3)) # 3
# Create immutable bag
fb = frozenbag('hello')
print(fb.count('l')) # 2Query element counts and access unique elements efficiently.
def count(self, value):
"""Return the number of times value appears in this bag.
Args:
value: The element to count
Returns:
int: Count of value in the bag (0 if not present)
"""
def num_unique_elements(self):
"""Return the number of unique elements.
Returns:
int: Number of distinct elements
"""
def unique_elements(self):
"""Return a view of unique elements in this bag.
Returns:
UniqueElementsView: View of unique elements
"""
def counts(self):
"""Return a view of (element, count) pairs.
Returns:
CountsView: View of element-count pairs
"""Modify bag contents by adding, removing, and updating elements.
def add(self, elem):
"""Add elem to the bag (increment its count by 1)."""
def remove(self, elem):
"""Remove one occurrence of elem from the bag.
Raises:
ValueError: If elem is not in the bag
"""
def discard(self, elem):
"""Remove one occurrence of elem from the bag if present."""
def pop(self):
"""Remove and return an arbitrary element from the bag.
Returns:
Any: An element from the bag
Raises:
KeyError: If bag is empty
"""
def clear(self):
"""Remove all elements from the bag."""
def discard_all(self, other):
"""Remove all elements from other, ignoring missing elements."""
def remove_all(self, other):
"""Remove all elements from other.
Raises:
ValueError: If any element in other has higher count than in self
"""Mathematical set operations that preserve element counts.
def __add__(self, other):
"""Return new bag with elements from both bags (counts added)."""
def __sub__(self, other):
"""Return new bag with elements of other removed from self."""
def __and__(self, other):
"""Return intersection (minimum counts for each element)."""
def __or__(self, other):
"""Return union (maximum counts for each element)."""
def __xor__(self, other):
"""Return symmetric difference (absolute difference of counts)."""
def issubset(self, other):
"""Check if every element in self has count <= in other."""
def issuperset(self, other):
"""Check if every element in self has count >= in other."""
def isdisjoint(self, other):
"""Return True if bags have no elements in common."""Usage examples:
a = bag('aab') # a:2, b:1
b = bag('abc') # a:1, b:1, c:1
print(a + b) # bag: a:3, b:2, c:1
print(a - b) # bag: a:1 (2-1)
print(a & b) # bag: a:1, b:1 (minimums)
print(a | b) # bag: a:2, b:1, c:1 (maximums)
print(a.issubset(bag('aaabbc'))) # TrueAdvanced operations for analysis and manipulation.
def product(self, other, operator=None):
"""Cartesian product of two bags.
Args:
other: Another iterable
operator: Optional function to combine elements instead of creating tuples
Returns:
bag: New bag with product elements
"""
@classmethod
def from_mapping(cls, mapping):
"""Create a bag from a dict of element->count.
Args:
mapping: Dict mapping elements to their counts
Raises:
ValueError: If any count is negative
"""
def copy(self):
"""Return a shallow copy of the bag."""Create hashable, immutable versions of bags for use as dictionary keys or set elements.
class frozenbag(Bag, Hashable):
def __hash__(self):
"""Return hash value for the frozenbag."""Usage examples:
from collections_extended import frozenbag
# Immutable bags can be used as dict keys
fb1 = frozenbag('abc')
fb2 = frozenbag('def')
mapping = {fb1: 'first', fb2: 'second'}
# Or in sets
bag_set = {frozenbag('hello'), frozenbag('world')}Specialized views providing different perspectives on bag contents.
class UniqueElementsView:
"""A view of unique elements in a bag."""
def __iter__(self): ...
def __contains__(self, elem): ...
def __len__(self): ...
class CountsView:
"""A view of (element, count) pairs in a bag."""
def __iter__(self): ...
def __contains__(self, item): ...
def __len__(self): ...Usage examples:
b = bag('hello world')
# Iterate over unique elements
for elem in b.unique_elements():
print(f"{elem}: {b.count(elem)}")
# Iterate over (element, count) pairs
for elem, count in b.counts():
print(f"{elem} appears {count} times")
# Check if specific count exists
print(('l', 3) in b.counts()) # TrueInstall with Tessl CLI
npx tessl i tessl/pypi-collections-extended