Lodash sort collection based on external array
This is the efficient & clean way:
(Import lodash identity
and sortBy
):
TS:
function sortByArray<T, U>({ source, by, sourceTransformer = identity }: { source: T[]; by: U[]; sourceTransformer?: (item: T) => U }) {
const indexesByElements = new Map(by.map((item, idx) => [item, idx]));
const orderedResult = sortBy(source, (p) => indexesByElements.get(sourceTransformer(p)));
return orderedResult;
}
Or in JS:
function sortByArray({ source, by, sourceTransformer = _.identity }) {
const indexesByElements = new Map(by.map((item, idx) => [item, idx]));
const orderedResult = _.sortBy(source, (p) => indexesByElements.get(sourceTransformer(p)));
return orderedResult;
}
Input:
var data1 = ['129asg', '39342aa'];
var data2 = [{
guid: '39342aa',
name: 'John'
}, {
guid: '129asg',
name: 'Mary'
}];
First create an index object, with
_.reduce
, like thisvar indexObject = _.reduce(data2, function(result, currentObject) { result[currentObject.guid] = currentObject; return result; }, {});
And then
map
the items of the first array with the objects from theindexObject
, like thisconsole.log(_.map(data1, function(currentGUID) { return indexObject[currentGUID] }));
Output
[ { guid: '129asg', name: 'Mary' },
{ guid: '39342aa', name: 'John' } ]
Note: This method will be very efficient if you want to sort so many objects, because it will reduce the linear look-up in the second array which would make the entire logic run in O(M * N) time complexity.
Here is just a simple add to the accepted answer in case you want to put the unmatched elements at the end of the sortedCollection and not at the beginning:
const last = collection.length;
var sortedCollection = _.sortBy(collection, function(item) {
return firstArray.indexOf(item.guid) !== -1? firstArray.indexOf(item.guid) : last;
});
var sortedCollection = _.sortBy(collection, function(item){
return firstArray.indexOf(item.guid)
});