
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@rimbu/multiset
Advanced tools
@rimbu/multisetFast, immutable multisets (bags) for TypeScript & JavaScript.
@rimbu/multiset provides efficient, type‑safe MultiSet implementations: set‑like collections
where each distinct element can appear multiple times, and the structure tracks how often each
element occurs. This is ideal when element frequency matters, such as counters, histograms,
weighted collections, or multi‑valued states.
Use it whenever you need to model “how many times” something appears rather than just whether it exists, without giving up immutability or strong typing.
@rimbu/multiset?@rimbu/multiset?Plain sets and maps only tell you whether a value is present, not how many times it occurs:
@rimbu/multiset focuses on:
If you ever maintain a Map<T, number> (or object) to track counts manually, a MultiSet is usually a
better fit.
sizeDistinct for unique values, size for total occurrences.HashMultiSet for fast hashing or SortedMultiSet for
deterministic ordering.MultiSet.createContext,
HashMultiSet.createContext, or SortedMultiSet.createContext.import { HashMultiSet } from '@rimbu/multiset';
// Create from individual values
const m = HashMultiSet.of('apple', 'banana', 'apple', 'orange');
// Total size vs number of distinct values
console.log(m.size); // 4
console.log(m.sizeDistinct); // 3
// Counts per element
console.log(m.count('apple')); // 2
console.log(m.count('banana')); // 1
// Updating counts returns a new multiset
const withMore = m.add('banana', 2);
console.log(withMore.count('banana')); // 3
Try Rimbu (including @rimbu/multiset) live in the browser using the
Rimbu Sandbox on CodeSandbox.
From @rimbu/multiset:
| Name | Description |
|---|---|
MultiSet<T> | Generic, type‑invariant multiset where values of type T can occur multiple times. |
MultiSet.NonEmpty<T> | Non‑empty refinement of MultiSet<T> with stronger guarantees. |
MultiSet.Context<UT> | Context/factory for creating MultiSet instances with configurable underlying map contexts. |
MultiSet.Builder<T> | Mutable builder for efficiently constructing a MultiSet before freezing it. |
VariantMultiSet<T> | Read‑only, type‑variant multiset; supports safe type‑widening but no mutating operations. |
VariantMultiSet.NonEmpty<T> | Non‑empty refinement of VariantMultiSet<T>. |
HashMultiSet<T> | Multiset backed by a HashMap for counts (hashed elements, fast unordered operations). |
HashMultiSet.Context<UT> | Context for HashMultiSet, exposing configuration and factories. |
HashMultiSet.Builder<T> | Builder type for HashMultiSet. |
SortedMultiSet<T> | Multiset backed by a SortedMap for counts (sorted elements, deterministic ordering). |
SortedMultiSet.Context<UT> | Context for SortedMultiSet. |
SortedMultiSet.Builder<T> | Builder type for SortedMultiSet. |
HashMultiSet)import { HashMultiSet } from '@rimbu/multiset';
// Construction
const empty = HashMultiSet.empty<number>();
const fromValues = HashMultiSet.of(1, 2, 2, 3);
// Size & distinct size
empty.isEmpty; // true
fromValues.size; // 4
fromValues.sizeDistinct; // 3
// Lookups
fromValues.has(2); // true
fromValues.count(2); // 2
fromValues.count(10); // 0
// Updating (returns new MultiSet)
const withMore = fromValues.add(2); // add one more '2'
const withSetCount = fromValues.setCount(3, 5); // set exact count for value 3
// Removing occurrences
const removedSome = fromValues.remove(2, { amount: 1 });
const removedAll = fromValues.remove(2, { amount: 'ALL' });
See the full MultiSet docs and API reference for all operations.
All concrete variants share the same MultiSet semantics but differ in how values are stored and
ordered internally:
import { HashMultiSet, SortedMultiSet } from '@rimbu/multiset';
// Hash-based multiset (fast, unordered)
const hashMulti = HashMultiSet.of('b', 'a', 'b');
hashMulti.stream().toArray(); // order not guaranteed
// Sorted multiset (deterministic value order)
const sortedMulti = SortedMultiSet.of('b', 'a', 'b');
sortedMulti.stream().toArray(); // ['a', 'b', 'b']
// Working with streams of distinct values
sortedMulti.streamDistinct().toArray(); // ['a', 'b']
If you need custom underlying contexts (e.g. custom hashers or comparators), you can create them via
HashMultiSet.createContext or SortedMultiSet.createContext:
import { HashMultiSet } from '@rimbu/multiset';
const context = HashMultiSet.createContext<number>({
countMapContext: /* optional: custom RMap.Context<number> */,
});
const multi = context.of(1, 2, 2, 3);
For read‑only, type‑variant views that can be safely widened, use the VariantMultiSet interfaces
exported from this package.
HashMap / SortedMap implementations
used for the internal count maps.StreamSource inputs, letting you construct and transform
MultiSets efficiently from arrays, iterables, or streams.For detailed performance characteristics and benchmarks, see the main Rimbu documentation at rimbu.org.
npm install @rimbu/multiset
# or
yarn add @rimbu/multiset
# or
bun add @rimbu/multiset
# or
deno add npm:@rimbu/multiset
@rimbu/multiset ships both ESM and CJS builds. Use it with any modern bundler
(Vite, Webpack, esbuild, Bun, etc.) or directly in Node ESM projects.
Q: How is a MultiSet different from a regular Set?
A MultiSet allows multiple occurrences per value and tracks their counts, while a regular Set
only tracks membership and stores each value at most once.
Q: What happens if I add the same value multiple times?
The count for that value increases: add, addAll, or addEntries will raise its occurrence count
instead of ignoring duplicates.
Q: Is the structure mutable?
No. All updates return new MultiSet instances; existing ones remain unchanged and can be safely
shared across your application.
Q: Can I iterate values or distinct values separately?
Yes. Use stream() to iterate all occurrences and streamDistinct() to iterate each distinct
value once.
@rimbu/hashed,
@rimbu/sorted, @rimbu/collection-types, and @rimbu/stream.Explore more at the Rimbu documentation and the MultiSet API docs.
We welcome contributions! See the Contributing guide for details.
Made with contributors-img.
MIT © Rimbu contributors. See LICENSE for details.
Created and maintained by Arvid Nicolaas. Logo © Rimbu.
FAQs
An immutable Set where each element can occur multiple times
The npm package @rimbu/multiset receives a total of 4,182 weekly downloads. As such, @rimbu/multiset popularity was classified as popular.
We found that @rimbu/multiset demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.