Lodash sortBy Order for Identical Values
When sorting collections using Lodash's _.sortBy,
encountering identical values or contradictory object property
evaluations can raise questions about how elements are positioned in the
final output. In these scenarios, the final index placement is strictly
governed by the algorithmic stability of Lodash's sorting
implementation, which relies on the original index order of the items in
the source array as the ultimate tie-breaker.
Algorithmic Stability in Lodash
Lodash implements a stable sorting algorithm. In computer science, a sorting algorithm is considered stable if two elements with equal keys appear in the sorted output in the same relative order as they appeared in the input dataset.
When you pass an array to _.sortBy, Lodash wraps each
element in an internal object that captures two critical pieces of
metadata:
- The computed criteria derived from the iteratee functions or property shorthands.
- The original index of the item within the source array.
Resolving Contradictory Object Properties
When an object contains conflicting properties—such as opposing flags or mixed values that resolve to the same derived sort weight—Lodash evaluates them based on the exact iteratees supplied:
- Iteratee Precedence: If multiple iteratees are
provided (e.g.,
_.sortBy(users, ['propA', 'propB'])), Lodash checks criteria in sequential order. A contradiction only matters if an earlier iteratee fails to break the tie. - Identical Evaluated Value: If custom iteratee logic
or inherent property values resolve to identical primitive comparison
values (e.g., both yield
0,true, or identical strings), Lodash considers the items indistinguishable by value.
The Final Determinant: Source Index Order
If two or more objects evaluate to identical values across all provided criteria, Lodash's internal comparator resolves the tie by comparing their original source indices.
Consider this example:
const items = [
{ id: 1, rank: 5, conflictFlag: true },
{ id: 2, rank: 5, conflictFlag: false }
];
// Sorting strictly by 'rank'
const result = _.sortBy(items, ['rank']);Even though { id: 1 } and { id: 2 } hold
contradictory values for conflictFlag, the sort iteratee
only evaluates rank. Because both have a rank
of 5, their computed keys are identical. Lodash bypasses
the unreferenced contradictory property and relies on the original array
sequence. Consequently, { id: 1 } retains a lower index
than { id: 2 } in the output.
If contradictory properties are evaluated within a custom iteratee and yield the exact same return value, the exact same rule applies. The element encountered first during the initial traversal of the input array will always be placed ahead of subsequent identical matches in the final sorted array.