| name | mongez-collection-math-aggregation |
| description | Tutorial-style "when to use which math method" guide for `@mongez/collection` — totaling, averaging, finding min/max/median, counting by predicate or by key, applying per-item arithmetic (`plus`/`minus`/`multiply`/`divide`/`modulus`/`increment`/`decrement`/`double`/`half`), parity filters (`even`/`odd`/`evenIndexes`/`oddIndexes`).
TRIGGER when: user asks "how do I total / aggregate / sum up / average a field across items", "how to apply a markup / discount to every item", "how to count items matching a condition", "what's the difference between count / countValue / countBy"; user explores math methods without a specific method name in mind; code shapes look like aggregating monetary or analytic fields with `collect(...)`.
SKIP: lookup-style "what does method X do" — use `mongez-collection-math` for the exact reference; one-shot aggregation without a chain — use `mongez-reinforcements-arrays`' standalone `sum`/`average`/`min`/`max`/`median`/`count`/`countBy` instead; filtering or sorting downstream of math — see `mongez-collection-querying` / `mongez-collection-sort-group`.
|
Math & Aggregation
When to use
- Summing, averaging, finding min/max, or computing medians over a list of numbers or object fields.
- Counting items that satisfy a condition, or counting how many times each value appears.
- Applying arithmetic (+, -, *, /) to every item or to a named field of every item.
How to use
Aggregate reducers
All four accept an optional key string (dot-notation supported) to operate on a field rather than the item itself.
const nums = collect([10, 20, 30]);
nums.sum();
nums.average();
nums.avg();
nums.min();
nums.max();
nums.median();
const orders = collect([
{ total: { price: 100 } },
{ total: { price: 200 } },
]);
orders.sum("total.price");
orders.average("total.price");
orders.min("total.price");
orders.max("total.price");
count — conditional count
collect(users).count(u => u.active);
collect(users).count("active");
countValue — exact value occurrences
collect(["a", "b", "a", "c"]).countValue("a");
countBy — frequency map per key value
collect(users).countBy("role");
Per-item arithmetic — plus, minus, multiply, divide, modulus
Two overloads each:
- Primitive items — single
amount argument.
- Keyed field —
(key, amount) arguments; returns a new collection with that field updated on each item.
collect([1, 2, 3]).plus(10);
collect([10, 20]).multiply(3);
collect([9, 6]).divide(3);
collect([10, 7]).modulus(3);
collect([{ age: 20 }, { age: 30 }]).plus("age", 5);
collect(items).multiply("price", 1.2);
increment / decrement — shorthand ±1
collect([1, 2, 3]).increment();
collect(items).increment("views");
collect(items).decrement("stock");
double / half — shorthand ×2 and ÷2
collect([5, 10]).double();
collect([10, 20]).half();
collect(items).double("price");
collect(items).half("discount");
even / odd — filter by numeric value parity
collect([1, 2, 3, 4]).even();
collect([1, 2, 3, 4]).odd();
collect(items).even("score");
evenIndexes / oddIndexes — filter by position parity
collect(["a","b","c","d"]).evenIndexes();
collect(["a","b","c","d"]).oddIndexes();
Key details / Pitfalls
min / max on an empty collection return 0 (matching @mongez/reinforcements convention). On a non-empty collection they find the true minimum/maximum, so a collection of all-positive numbers will not incorrectly return 0 for max.
sum, average, and median delegate directly to @mongez/reinforcements' helpers.
- Keyed arithmetic does not mutate plain-object items.
plus("age", 5) shallow-clones each plain-object item via cloneForSet before calling set(clone, key, value), so the originals in the source collection are safe. Class instances and nested object references are still passed through by reference (the clone is shallow) — deep-clone the input first if deep immutability is required.
divide throws Error("Cannot divide by zero") and modulus throws Error("Cannot have a modulus of zero") when the divisor is 0.
- All per-item math methods return a new collection — they do not mutate
this.items.