{"id":7436,"library":"multiset","title":"Multiset","description":"An implementation of a multiset, similar to Python's built-in `set` but allowing elements to occur multiple times. It supports standard set operations like union, intersection, and difference. The library is actively maintained, with version 3.2.0 released in 2024, and incorporates regular updates for new Python versions and minor feature enhancements.","status":"active","version":"3.2.0","language":"en","source_language":"en","source_url":"https://github.com/wheerd/multiset","tags":["data-structure","multiset","set","collection"],"install":[{"cmd":"pip install multiset","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"symbol":"Multiset","correct":"from multiset import Multiset"},{"note":"The `FrozenMultiset` class was introduced in version 2.0.0 to provide an immutable, hashable multiset, replacing the need for manual 'freezing' or reliance on the mutable `Multiset` for hashable contexts.","wrong":"from multiset import Multiset; my_frozenset = Multiset([...]).freeze() # Old pattern or misunderstanding of API","symbol":"FrozenMultiset","correct":"from multiset import FrozenMultiset"}],"quickstart":{"code":"from multiset import Multiset, FrozenMultiset\n\n# Create a mutable multiset from an iterable\nm1 = Multiset('banana')\nprint(f\"Initial multiset: {m1}\")\n# Output: Initial multiset: {b, a, n, a, n, a}\n\n# Add elements\nm1.add('apple', multiplicity=2)\nprint(f\"After adding apples: {m1}\")\n# Output: After adding apples: {b, a, n, a, n, a, apple, apple}\n\n# Check multiplicity (count) of an element\nprint(f\"Count of 'a': {m1.get('a')}\")\n# Output: Count of 'a': 3\n\n# Perform set operations\nm2 = Multiset(['a', 'p', 'p', 'l', 'e'])\nintersection = m1 & m2\nprint(f\"Intersection of m1 and m2: {intersection}\")\n# Output: Intersection of m1 and m2: {a, a, apple, p, l, e}\n\n# Create an immutable, hashable multiset\nf1 = FrozenMultiset([1, 1, 2, 3])\nf2 = FrozenMultiset([1, 2, 2, 4])\nprint(f\"Frozen multiset f1: {f1}\")\n# Output: Frozen multiset f1: {1, 1, 2, 3}\n\n# Frozen multisets can be used in sets or as dict keys\nmy_set_of_multisets = {f1, f2}\nprint(f\"Set of frozen multisets: {my_set_of_multisets}\")\n# Output: Set of frozen multisets: {{1, 1, 2, 3}, {1, 2, 2, 4}}","lang":"python","description":"Demonstrates how to create mutable and immutable multisets, add elements, check multiplicities, and perform basic set operations."},"warnings":[{"fix":"Ensure your Python environment is running Python 3.8 or higher.","message":"Python 3.7 is no longer supported starting from `multiset` version 3.1.0. Additionally, support for Python 2.7 and 3.6 was dropped in version 3.0.0.","severity":"breaking","affected_versions":">=3.0.0 (for 2.7/3.6 drop), >=3.1.0 (for 3.7 drop)"},{"fix":"Consult the official `multiset` API documentation for the correct method names and signatures. For example, use `multiset_instance.distinct_elements()` for distinct keys, or `multiset_instance.items()` for (element, multiplicity) pairs.","message":"In version 2.0.0, the `Multiset` class ceased direct inheritance from `dict`. Consequently, some `dict` methods (e.g., `keys()`, `values()`, `items()`, `fromkeys()`, `get()`, `setdefault()`, `pop()`, `popitem()`) were either removed, renamed, or had their signatures altered.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"If a hashable multiset is required, use `FrozenMultiset`. For example, `my_dict = {FrozenMultiset([1, 2]): 'value'}`.","message":"The mutable `Multiset` object is not hashable and therefore cannot be used as a dictionary key or as an element in a `set`. The `FrozenMultiset` class, introduced in version 2.0.0, provides an immutable and hashable alternative.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Be aware that elements with zero (or negative) counts are not stored or represented. If you need to track zero or negative counts, `collections.Counter` from the standard library might be a more suitable data structure.","message":"Unlike `collections.Counter`, the `multiset` library automatically removes elements from the multiset whose multiplicity reaches zero. It also strictly only allows positive counts during initialization and other operations.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Use `FrozenMultiset` for scenarios requiring hashability. For example: `my_dict = {FrozenMultiset([1, 2]): 'value'}`.","cause":"Attempting to use a mutable `Multiset` object as a key in a dictionary or as an element in a set (or frozenset).","error":"TypeError: unhashable type: 'Multiset'"},{"fix":"Use the `multiset` equivalent methods. For `keys`, use `multiset_instance.distinct_elements()`. For `items`, use `multiset_instance.items()`. Refer to the official API documentation for replacements.","cause":"Attempting to use a `dict`-specific method (`keys`, `values`, `items`, `popitem`, etc.) directly on a `Multiset` object after the API change in version 2.0.0.","error":"AttributeError: 'Multiset' object has no attribute 'keys'"},{"fix":"For `get`, always provide a `default` argument, e.g., `my_multiset.get(element, 0)`. For `setdefault`, ensure the `default` is positive if you expect a new element to be added. Use `discard()` if you want to remove an element without raising an error if it's missing.","cause":"The `Multiset.get()` method requires a `default` argument (unlike `dict.get()`). `Multiset.setdefault()` also requires a `default` and will only add an element if the default is positive. Using `multiset_instance.remove(element)` or `del multiset_instance[element]` will raise a `KeyError` if the element is not present, unlike `multiset_instance.discard(element)` which will not.","error":"KeyError: 'element_name' (from get, setdefault, remove, or del)"}]}