'Sort array by number from other array
I have two arrays and I want to sort first one based on some values from another array:
const items = [
['music', ['arr']],
['movies', ['arr']],
['quizes', ['arr']],
['series', ['arr']]
];
const categories = [
{ name: "music", priority: 3},
{ name: "movies", priority: 2},
{ name: "quizes", priority: 5},
{ name: "series", priority: 1},
{ name: "sports", priority: 4},
];
I want to sort my first array, by property 'priority' from my second array -> from the biggest one.
Like this:
const expectedResult = [
['quizes', ['arr']],
['music', ['arr']]
['movies', ['arr']],
['series', ['arr']],
];
This is what I tried but without success.
const sorted = items.sort((a,b) => {
const [aKey, aVal] = a;
const [bKey, bVal] = b;
const prio = categories.filter(c => c.name === aKey)[0];
// not sure how to use this prio
return aKey.priority - bKey.priority;
})
Solution 1:[1]
You can use sort() method and check the priority from the categories
const items = [
['music', ['arr']],
['movies', ['arr']],
['quizes', ['arr']],
['series', ['arr']],
];
const categories = [
{ name: 'music', priority: 3 },
{ name: 'movies', priority: 2 },
{ name: 'quizes', priority: 5 },
{ name: 'series', priority: 1 },
{ name: 'sports', priority: 4 },
];
const result = items.sort(([a], [b]) => {
const aPriority = categories.find(({ name }) => name === a).priority;
const bPriority = categories.find(({ name }) => name === b).priority;
return bPriority - aPriority;
});
console.log(result);
Solution 2:[2]
You really do not want to use find() or filter() inside of the sort method because it is expensive. On every iteration, you are looking up the data in the array. So you are looping a lot. There is better ways to get the index.
Easiest thing is to make a lookup object so you are not having to search the other array over and over for a match. So if you can change categories to an object from the start, it will make your life so much easier.
In the sort I added max value in case the key is not defined. Now this would backfire if you had a value of zero since it is just a truthy check.
const items = [
['music', ['arr']],
['movies', ['arr']],
['quizes', ['arr']],
['series', ['arr']]
];
const categories = {
music: 3,
movies: 2,
quizes: 5,
series: 1,
sports: 4,
};
items.sort(([keyA], [keyB]) => (categories[keyA] || Number.MAX_VALUE) - (categories[keyB] || Number.MAX_VALUE));
console.log(items);
If you can not make the object look like that and you have to use the array, you can convert it from the array to an object. That can be done a few ways. I like to use reduce.
const items = [
['music', ['arr']],
['movies', ['arr']],
['quizes', ['arr']],
['series', ['arr']]
];
const categories = [
{ name: "music", priority: 3},
{ name: "movies", priority: 2},
{ name: "quizes", priority: 5},
{ name: "series", priority: 1},
{ name: "sports", priority: 4},
];
const lookup = categories.reduce((acc, obj) => ({...acc, [obj.name]: obj.priority}), {});
items.sort(([keyA], [keyB]) => (lookup[keyA] || Number.MAX_VALUE) - (lookup[keyB] || Number.MAX_VALUE));
console.log(items);
Now if you are sure that all of the keys will exist in the categories, you can drop the max value
items.sort(([keyA], [keyB]) => lookup[keyA] - lookup[keyB];
Solution 3:[3]
You could take an object for the order and sort by delta.
const
items = [['music', ['arr']], ['movies', ['arr']], ['quizes', ['arr']], ['series', ['arr']]],
categories = [{ name: "music", priority: 3 }, { name: "movies", priority: 2 }, { name: "quizes", priority: 5 }, { name: "series", priority: 1 }, { name: "sports", priority: 4 }],
order = Object.fromEntries(
categories.map(({ name, priority }) => [name, priority])
);
items.sort(([a], [b]) => order[a] - order[b]);
console.log(items);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | Nina Scholz |
