Lodash sortedUniqBy with Different Object Shapes
Lodash's _.sortedUniqBy processes sorted arrays by
running an iteratee function over each element and discarding adjacent
duplicates based on the returned values. When dealing with objects of
differing shapes where the iteratee yields the exact same value, the
method strictly adheres to a "first seen, first kept" policy. It
completely ignores structural, type, or property differences outside of
the iteratee's output, preserving only the first occurrence among
consecutive duplicates and omitting the rest.
The Comparison Mechanism
_.sortedUniqBy is optimized specifically for arrays that
are already sorted according to the criteria defined by the iteratee.
Unlike _.uniqBy, which typically checks every item against
a set of all previously seen values, _.sortedUniqBy only
compares the iteratee result of the current item to the iteratee result
of the immediately preceding retained item.
The algorithm uses the SameValueZero comparison on the
values produced by the iteratee:
- The iteratee function executes on the first element, and this element is automatically added to the result array.
- The iteratee executes on the next element.
- If the computed value matches the computed value of the previously kept element, the current element is discarded.
- If the computed value differs, the current element is retained, and its computed value becomes the new baseline for subsequent comparisons.
Processing Differing Object Shapes
JavaScript objects can have entirely different schemas, keys, or
prototype chains. However, _.sortedUniqBy is structurally
agnostic. It does not perform a deep comparison, nor does it attempt to
merge properties across differing shapes.
Consider an example where the iteratee extracts an id
property:
const items = [
{ id: 10, name: 'Alpha', active: true },
{ id: 10, title: 'Beta', metadata: { role: 'admin' } },
{ id: 20, type: 'Gamma' }
];
const result = _.sortedUniqBy(items, 'id');The resulting array will be:
[
{ id: 10, name: 'Alpha', active: true },
{ id: 20, type: 'Gamma' }
]Even though the second object contains keys (title,
metadata) that the first object lacks,
_.sortedUniqBy only evaluates the property
'id'. Because both return 10, the second
object is deemed a duplicate and discarded.
Critical Considerations
- First-In Priority: The retained object is always the earliest one encountered in the consecutive sequence. If critical data exists in the subsequent shapes, it will be lost unless the array is pre-processed or merged.
- Sorted Order Requirement: Because the method checks adjacent results, differing shapes with matching iteratee outputs must be contiguous. If identical iteratee values are separated by different values, both will appear in the output.
- Undefined Iteratee Results: If an object shape does
not contain the property specified by a shorthand iteratee string, the
iteratee yields
undefined. Consecutive objects missing the target property will also be collapsed down to the first object in the sequence, regardless of how their other properties differ.