Lodash _.invertBy() method
What you’ll learn
- How
_.invertBy(object, [iteratee])turns a source object into{ bucketKey: [...sourceKeys] }. - How the optional iteratee derives the bucket key from each value.
- When
_.invertBywins over _.invert()—every duplicate value is preserved as an array entry. - Common shorthand forms: function, property name,
[path, value], and matcher object.
Prerequisites
You should be comfortable with iteratee shorthands and know that _.invert loses keys when values collide. _.invertBy is the duplicate-safe variant.
- Always arrays: each bucket is an array, even when only one source key landed in it.
- Iteratee shorthands: function, string,
[path, value], and matcher object are all valid. - Pure function: returns a new object; the input is never mutated.
Overview
_.invertBy walks the source object’s own enumerable string-keyed properties. For each entry it asks the iteratee “which bucket does this value belong to?” and appends the source key to that bucket. The result is a tidy { bucketKey: [keys] } structure—perfect for grouping and reverse-lookup.
Duplicate-safe
Repeated values are collected into the same bucket. Nothing is overwritten.
Iteratee-driven buckets
Group by a property, a formula, or any function you like—not just the raw value.
Pure transform
A new object every time. Safe to call from selectors and memoized helpers.
Syntax
_.invertBy(object, [iteratee=_.identity]) - object: any object to invert. Only own enumerable string-keyed properties are walked.
- iteratee (optional): function, property name string,
[path, value], or matcher object. It receives the source value and returns the bucket key. Defaults to the value itself. - Returns: a new object of buckets, each one an array of source keys.
Group source keys by their value
Without an iteratee, _.invertBy simply collects every source key under its stringified value.
import invertBy from "lodash/invertBy";
const items = {
apple: "fruit",
banana: "fruit",
carrot: "vegetable"
};
invertBy(items);
// -> { fruit: ["apple", "banana"], vegetable: ["carrot"] }
const scores = { A: 1, B: 2, C: 1, D: 3 };
invertBy(scores);
// -> { "1": ["A", "C"], "2": ["B"], "3": ["D"] } Custom buckets with an iteratee
Pass a function to derive the bucket key. This is the workflow for grouping by length, range, category, status flags, and so on.
import invertBy from "lodash/invertBy";
const fruits = {
1: "apple",
2: "banana",
3: "orange"
};
invertBy(fruits, (name) => name.length);
// -> { "5": ["1"], "6": ["2", "3"] }
// apple -> 5; banana, orange -> 6
const orders = {
o1: 42,
o2: 7,
o3: 105,
o4: 23
};
invertBy(orders, (amount) => amount >= 50 ? "large" : "small");
// -> { small: ["o1", "o2", "o4"], large: ["o3"] } Iteratee shorthands for nested values
When values are objects, pass a property name string instead of writing a function. The four classic Lodash shorthands all apply.
import invertBy from "lodash/invertBy";
const users = {
alice: { id: 1, age: 25, role: "admin" },
bob: { id: 2, age: 30, role: "user" },
charlie: { id: 3, age: 25, role: "user" },
dana: { id: 4, age: 30, role: "admin" }
};
invertBy(users, "age");
// -> { "25": ["alice", "charlie"], "30": ["bob", "dana"] }
invertBy(users, "role");
// -> { admin: ["alice", "dana"], user: ["bob", "charlie"] }
invertBy(users, { role: "admin" });
// -> { true: ["alice", "dana"], false: ["bob", "charlie"] }
// Matcher shorthand returns booleans, which become string keys. 📋 _.invertBy vs related helpers
| Topic | _.invertBy | _.invert | _.groupBy |
|---|---|---|---|
| Input | Object | Object | Collection (array or object) |
| Bucket value | Array of source keys | One source key (last wins) | Array of source items |
| Duplicates handled | Yes | No, overwritten | Yes |
| Iteratee shorthands | Yes | No | Yes |
| Mutates input | No | No | No |
Use _.invertBy when you want to remember which keys ended up in each bucket. Use _.groupBy when you want the original values in each bucket. Use _.invert only when values are guaranteed unique.
Pitfalls to avoid
Bucket keys are always strings
Numbers, booleans, and other primitives are stringified when they become object keys. TypeScript will see them as string keys after the inversion.
Returning objects from the iteratee collapses buckets
If your iteratee returns a non-primitive, all results stringify to "[object Object]" and merge into one bucket. Return a primitive identifier instead.
Bucket array order follows source iteration
The array of source keys reflects Lodash key iteration order. If you need lexicographic order, sort the array yourself.
Own enumerable string keys only
Symbol-keyed and inherited properties are ignored. Reach for a manual loop if you need them.
❓ FAQ
Summary
- Purpose: invert an object into
{ bucketKey: [sourceKeys] }, optionally driven by an iteratee. - Remember: the right-hand side is always an array, and bucket keys are stringified.
- Next: Lodash _.invoke(), _.invert(), or the official Lodash docs for _.invertBy.
_.invertBy always produces buckets (arrays) on the right-hand side, even when a value is unique. Use _.invert if you specifically want flat { value: key } pairs and you know every value is one-of-a-kind.
5 people found this page helpful
