I'm trying to refactor a piece of code in a less verbose methods.
Basically I have this array of user skills:
const skills = ['add', 'edit', 'delete', 'secondSkill', 'fourthSkill']
Then I have an array of select options:
const options = [
{
label: "First",
value: "firstSkill"
},
{
label: "Second",
value: "secondSkill"
},
{
label: "Third",
value: "thirdSkill"
},
{
label: "Fourth",
value: "fourthSkill"
}
];
I'm trying to write a method that:
- find the common elements between arrays skills and options
- return ONLY the common element with the biggest index in the options array
For example: in this case I want to return fourthSkill because is the element with the biggest index in my options array.
I came up with something like that:
const findDefaultValue = (selectOptions, userSkills) => {
const commonItems = selectOptions.filter((opt) =>
userSkills.includes(opt.value)
);
const findIndexes = commonItems.map((item) => {
return selectOptions.indexOf(item);
});
const maxIndex = Math.max(...findIndexes);
return options[maxIndex];
};
It kinda works, but I would like to hear from you if there are shorter ways to do it. Thanks!
CodePudding user response:
You can just return the last item of commonItems
, like:
const findDefaultValue = (selectOptions, userSkills) => {
const commonItems = selectOptions.filter((opt) =>
userSkills.includes(opt.value)
);
return commonItems.at(-1);
}
In the future, you'll be able to use findLast
, like:
const findDefaultValue = (selectOptions, userSkills) => {
return selectOptions.findLast((opt) =>
userSkills.includes(opt.value)
);
};
CodePudding user response:
Another one solution. One-liner if you don't mind.
const skills = ['add', 'edit', 'delete', 'secondSkill', 'fourthSkill']
const options = [{label: "First",value: "firstSkill"}, {label: "Second",value: "secondSkill"}, {label: "Third", value: "thirdSkill"}, {label: "Fourth",value: "fourthSkill"}];
const result = options.reverse().find(({ value }) => skills.includes(value));
console.log(result);
.as-console-wrapper{min-height: 100%!important; top: 0}
CodePudding user response:
Since the particular index is not important, and all you need is just one element, you can iterate through a reversed copy of the array and return the first element that matches.
const skills = ['add', 'edit', 'delete', 'secondSkill', 'fourthSkill']
const options = [{label: "First",value: "firstSkill"}, {label: "Second",value: "secondSkill"}, {label: "Third", value: "thirdSkill"}, {label: "Fourth",value: "fourthSkill"}];
const findDefaultValue = (selectOptions, userSkills) => {
for(const {label, value} of [...selectOptions].reverse()) {
if( userSkills.includes(value) ) {
return {label,value};
}
}
return 'NONE FOUND';
};
console.log( findDefaultValue(options, skills) );
/*OUTPUT:
{
"label": "Fourth",
"value": "fourthSkill"
}
*/
Alternatively, you can use @AlexandrBelan's one-liner with the caveat of using a copy, so options
remains unchanged:
const skills = ['add', 'edit', 'delete', 'secondSkill', 'fourthSkill']
const options = [{label: "First",value: "firstSkill"}, {label: "Second",value: "secondSkill"}, {label: "Third", value: "thirdSkill"}, {label: "Fourth",value: "fourthSkill"}];
const findDefaultValue =
(selectOptions, userSkills) =>
[...selectOptions].reverse().find(({value}) => userSkills.includes(value));
console.log( findDefaultValue(options, skills) );
/*OUTPUT:
{
"label": "Fourth",
"value": "fourthSkill"
}
*/