'Can I sort an array of objects based on a array of subarrays?
I would ask a question regarding sorting.
Let's say I have an array of objects:
let arrayToBeSorted = [
{
name:"name1",
id:"id1",
},
{
name:"name2",
id:"id2",
},
{
name:"name3",
id:"id3",
},
{
name:"name4",
id:"id4",
},
{
name:"name5",
id:"id5",
},
{
name:"name6",
id:"id6",
}];
And Let's say I have an array of sub arrays which each one is containing IDs string like that:
let sortArray = [["id2", "id1"], ["id5"], ["id6","id3","id4"]]
What I want to do is to sort the arrayToBeSorted based on the sortArray preserving each subarrays (in order to maintain an hermetic order)
This is the wanted result:
arrayToBeSorted = [
{
name:"name2",
id:"id2",
},
{
name:"name1",
id:"id1",
},
{
name:"name5",
id:"id5",
},
{
name:"name6",
id:"id6",
},
{
name:"name3",
id:"id3",
},
{
name:"name4",
id:"id4",
}];
EDIT: I tried to:
arrayToBeSorted.sort((a,b)=> for(var i=0; i<sortArray.length;i++)
{
sortArr.indexOf(a.item.id) - sortArr.indexOf(b.item.id)
});
I also thought of sorting by each array and the concat the sorted result, but no success...
Thanks!
Solution 1:[1]
You seem to be overcomplicating the sort operation here. Use sort() on arrayToBeSorted and get the indexOf each array element in a flat()tened copy of sortArray:
let arrayToBeSorted = [{
name: "name1",
id: "id1",
}, {
name: "name2",
id: "id2",
}, {
name: "name3",
id: "id3",
}, {
name: "name4",
id: "id4",
}, {
name: "name5",
id: "id5",
}, {
name: "name6",
id: "id6",
}];
let sortArray = [
["id2", "id1"],
["id5"],
["id6", "id3", "id4"]
];
console.log(arrayToBeSorted.sort((a, b) => sortArray.flat().indexOf(a.id) - sortArray.flat().indexOf(b.id)));
Solution 2:[2]
You could flat the array and build an object with wanted order and sort the array.
const
data = [{ name: "name1", id: "id1" }, { name: "name2", id: "id2" }, { name: "name3", id: "id3" }, { name: "name4", id: "id4" }, { name: "name5", id: "id5" }, { name: "name6", id: "id6" }],
sortArray = [["id2", "id1"], ["id5"], ["id6", "id3", "id4"]],
order = Object.fromEntries(sortArray.flat().map((k, i) => [k, i + 1]));
data.sort((a, b) => order[a.id] - order[b.id]);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Solution 3:[3]
You can use sort() based on a flattened sortArray using findIndex() or indexOf() as @esqew. You could also go a step further and pre-process sortArray and create an object ids as keys and indices of sortArray as values. Then the sort function would be based on the object as follows:
let arrayToBeSorted = [{
name: "name1",
id: "id1",
},
{
name: "name2",
id: "id2",
},
{
name: "name3",
id: "id3",
},
{
name: "name4",
id: "id4",
},
{
name: "name5",
id: "id5",
},
{
name: "name6",
id: "id6",
}
];
let sortArray = [["id2", "id1"], ["id5"], ["id6","id3","id4"]];
const flatO = Object.fromEntries( sortArray.flat().map((id,i) => [id,i]) );
const sortedArray = arrayToBeSorted.sort((a,b) => flatO[a.id] - flatO[b.id]);
console.log( sortedArray );
NOTE: This is equivalent to @NinaScholz's solution. Saw it just after I posted this. I have upvoted both @NinaScholz's and @esqew's solutions but I would take @NinaScholz's since the flat() method including the creation of the order object execute JUST ONCE.
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 | esqew |
| Solution 2 | |
| Solution 3 |
