Lodash _.sortedLastIndexBy() method
What you’ll learn
- How
_.sortedLastIndexBy(array, value, iteratee)finds the upper insertion boundary on projected keys. - Why pairing it with _.sortedIndexBy() counts duplicate projections in O(log n) time.
- When function iteratees diverge from simple property paths.
- Try each example in the editor (
?tryit=1,2,3) with Lodash from a CDN.
Prerequisites
Comfort with _.sortedLastIndex() (bisect right without iteratees) and _.sortedIndexBy() (bisect left with iteratees) smooths the mental model.
- Your dataset stays sorted ascending by whatever the iteratee measures.
- You can run snippets in Node or open the Try-it labs in a browser.
Overview
_.sortedLastIndexBy merges iteratee ergonomics with bisect-right semantics: project rows and needles uniformly, then ask Lodash for the trailing edge of the band where that projection could live.
Upper fence
Duplicate streaks end where this index begins—ideal for histogram buckets or quota bands.
Iteratee parity
Strings, paths, or unary functions—Lodash applies the same rule to stored rows and the probe payload.
Count shortcut
Subtract paired left/right indexes to tally tied projections without extra scans.
Syntax
_.sortedLastIndexBy(array, value, iteratee) - array: ascending sorted by
iteratee(element). - value: candidate compared through
iteratee(value). - iteratee: Lodash shorthand as in other
*Byhelpers. - Returns: greatest insertion index in
[0, array.length]preserving ascending projected order.
Bracketing duplicate scores
Subtract sortedIndexBy from sortedLastIndexBy to learn how many rows share the same projection.
import sortedIndexBy from "lodash/sortedIndexBy";
import sortedLastIndexBy from "lodash/sortedLastIndexBy";
const rows = [
{ id: "a", score: 10 },
{ id: "b", score: 20 },
{ id: "c", score: 20 },
{ id: "d", score: 20 },
{ id: "e", score: 30 }
];
const needle = { id: "x", score: 20 };
const lo = sortedIndexBy(rows, needle, "score");
const hi = sortedLastIndexBy(rows, needle, "score");
const width = hi - lo;
// lo → 1, hi → 4, width → 3 Function iteratee
Even when each projection occurs once, bisect right lands after the equal neighbor—one slot past bisect left.
import sortedIndexBy from "lodash/sortedIndexBy";
import sortedLastIndexBy from "lodash/sortedLastIndexBy";
const words = ["a", "bb", "ccc"];
const len = (w) => w.length;
sortedIndexBy(words, "xx", len); // → 1
sortedLastIndexBy(words, "xx", len); // → 2 Property path gap
Between distinct years both helpers agree—the interval collapses to a single insertion point.
import sortedLastIndexBy from "lodash/sortedLastIndexBy";
const releases = [
{ name: "v1", year: 2000 },
{ name: "v2", year: 2010 },
{ name: "v3", year: 2020 }
];
sortedLastIndexBy(releases, { name: "patch", year: 2015 }, "year");
// → 2 📋 _.sortedLastIndexBy vs _.sortedIndexBy vs _.sortedLastIndex
| API | Edge |
|---|---|
_.sortedIndexBy(...) | Bisect left on projections. |
_.sortedLastIndexBy(...) | Bisect right on projections. |
_.sortedLastIndex(array, value) | Bisect right without an iteratee. |
Pitfalls to avoid
Projection mismatch
Sorting by one field but indexing another breaks monotonicity—keep iteratee aligned with the comparator that produced the array.
sortedLastIndexOf confusion
Membership helpers return -1 on misses; insertion helpers always pick a fence inside [0, length].
Heavy iteratees
Each probe evaluates the iteratee—prefer cheap getters when arrays grow large.
❓ FAQ
Summary
- Purpose:
_.sortedLastIndexBy(array, value, iteratee)returns the upper insertion index after projecting both sides. - Workflow: pair with
sortedIndexByto measure duplicate spans or reserve inclusive windows. - Next: Lodash _.sortedLastIndexOf(), _.sortedLastIndex() (previous), or the array methods hub.
_.sortedIndexBy() pins the lower edge of a projection band; sortedLastIndexBy closes the upper edge—subtract the two to count rows sharing the same projected key without scanning.
6 people found this page helpful
