There are like these datas
const persons = [
{
label: "jhon",
value: 1
},
{
label: "Mary",
value: 2
},
{
label: "Michelle",
value: 3
},
{
label: "David",
value: 4
},
{
label: "Kerry",
value: 5
},
{
label: "Tom",
value: 6
}
];
const testPassedPersons = [3, 5, 6];
What do I want to do?
I need to move these persons who includes testPassedPersons number to head of array.
So now Michelle / Kerry / Tom should move, value in order from smallest to largest [3,5,6]
▼ What I need to get
const SortedPersons = [
{
label: "Michelle",
value: 3
},
{
label: "Kerry",
value: 5
},
{
label: "Tom",
value: 6
}
{
label: "jhon",
value: 1
},
{
label: "Mary",
value: 2
},
{
label: "David",
value: 4
},
];
What I’ve tried so far
actually I have a solution, but I would like to know alternative better way (specially shorter or faster)
▼ This is my way
const sortedPersons = [
...persons.filter((person) => testPassedPersons.includes(person.value)),
...persons.filter((person) => !testPassedPersons.includes(person.value))
];
▼ codesandbox url.
https://codesandbox.io/s/pensive-david-1giqnk?file=/src/index.js
5
Answers
This is what I got:
As code shows, I am creating a set because set will hold only unique values. We add the persons with the values in testPassedPersons, then add the rest of the persons. Since set holds unique items, the duplication won’t occur.Then, at the end, we just turn that set into an array.
you can write a custom sort function.
indexOf
returns-1
if element is not found in the array.So if
aIndex
is not -1 andbIndex
is -1 it means both not found. therefore keep original order of a and b.If
aIndex
is -1 only we return 1 means a should come after b.If
bIndex
is -1 only we return -1 means a should come before b (b after a). So basically what is not found intestPassedPersons
comes after.Finally
indexA - indexB
will decide which comes first based on the sign.the implementation with 2 filters will give
Mary,Michelle,Kerry,Tom
for[3, 5, 6, 2]
insteadMichelle,Kerry,Tom,Mary
. If that is the desired result you can achieve it in 1 loop instead of 2 filters(2 loops) usingreduce
. Also converting the passed person array to a set can help achieve O(1) lookupYou could build an object with the wanted order and sort by
value
or move the items to bottom.This approach allows to move any unknown item/
value
either to top (value smaller than zero), bottom (a large value, likeNumber.MAX_VALUE
) or just inbetween the given order.I don’t think there’s anything really wrong with your current approach. You could save yourself a loop over the array with a partition function rather than a filter function.
The idea with the partition function is to push the matching results into the first array (equivalent to the filter results) and then push all the others into a second array, so you have two arrays, one of matching and one of not matching results.
A number of JS libraries have partition functions e.g. Lodash and Ramda.
You can simply achieve this with the help of
Array.splice()
method along withArray.unshift()
method.Live Demo :