Lodash _.sortedIndexBy() method
What you’ll learn
- How
_.sortedIndexBy(array, value, iteratee)compares projected scalars instead of whole objects. - Why the backing array must already be sorted by that projection in ascending order.
- How bisect-left semantics carry over from _.sortedIndex().
- Try each example in the editor (
?tryit=1,2,3) with Lodash from a CDN.
Prerequisites
Read _.sortedIndex() first for bisect-left behavior; skim _.differenceBy() if iteratee shorthand is still fuzzy.
- You can read Lodash iteratees as either property paths (
"score") or unary functions. - You can run snippets in Node or open the Try-it labs in a browser.
Overview
_.sortedIndexBy is the ergonomic variant for ordered collections of records: project each row (and the needle) through one iteratee, binary-search on those projections, and emit the leftmost insertion slot.
Projected compare
Sort keys can live deep inside objects without flattening the dataset first.
Same bisect rule
Equal projections still resolve to the earliest viable slot—stable insertion semantics.
Zero mutation
Use the returned index with splice, immutable updates, or gap filling—Lodash never writes for you.
Syntax
_.sortedIndexBy(array, value, iteratee) - array: collection sorted ascending by
iteratee(element). - value: probe compared via
iteratee(value)against each projection. - iteratee: Lodash iteratee shorthand—string path, keyed property, or function.
- Returns: integer insert index in
[0, array.length]preserving ascending projected order.
Property path
Rows stay objects while ordering rides on the numeric year field.
import sortedIndexBy from "lodash/sortedIndexBy";
const releases = [
{ name: "v1", year: 2000 },
{ name: "v2", year: 2010 },
{ name: "v3", year: 2020 }
];
sortedIndexBy(releases, { name: "patch", year: 2015 }, "year");
// → 2 Function iteratee
Strings sort by derived signal—in this case each token’s length.
import sortedIndexBy from "lodash/sortedIndexBy";
const words = ["a", "bb", "ccc"]; // lengths 1, 2, 3
sortedIndexBy(words, "xx", (w) => w.length);
// → 1 (length 2 belongs before "ccc") Duplicate projections
Repeated scores behave like duplicate numbers in plain sortedIndex: left bias on ties.
import sortedIndexBy from "lodash/sortedIndexBy";
const rows = [
{ id: "a", score: 10 },
{ id: "b", score: 20 },
{ id: "c", score: 20 },
{ id: "d", score: 30 }
];
sortedIndexBy(rows, { id: "x", score: 20 }, "score");
// → 1 📋 _.sortedIndexBy vs _.sortedIndex vs _.sortedLastIndexBy
| API | Compared values |
|---|---|
_.sortedIndex(array, value) | Raw elements (default comparator). |
_.sortedIndexBy(array, value, iteratee) | iteratee(element) vs iteratee(value) with bisect left. |
_.sortedLastIndexBy(array, value, iteratee) | Same projections, but bisect right for upper insertion bounds. |
Pitfalls to avoid
Wrong sort key
Rows sorted by display name but searched by timestamp still violate the precondition—align iteratee with the ordering that built the array.
Incomparable projections
undefined projections or unstable compares (NaN) make binary search unreliable—normalize before indexing.
Heavy iteratees
Each midpoint still invokes the iteratee—keep work O(1) per comparison for predictable performance.
❓ FAQ
Summary
- Purpose:
_.sortedIndexBy(array, value, iteratee)finds the leftmost insert index using projected comparisons. - Precondition: projections must be strictly ascending-sorted along the path your iteratee measures.
- Next: Lodash _.sortedIndexOf(), _.sortedIndex() (previous), or the array methods hub.
If _.sortedIndex() compares raw slots, sortedIndexBy lifts that logic through the same iteratee shorthand family used by _.differenceBy()—perfect when rows are objects but ordering keys are numeric timestamps or short codes.
6 people found this page helpful
