Reputation: 43
I want to find a better, more elegant solution than using 2 iteration to find a value in an object. I looked at functions to search within an array such as find,indexOf but was wondering I could search through the object without using a for or forEach.
Let say I want to find all swimmers. What I got so far.
members = [
{ name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
{ name: "Sam", hobby: ["Cars", "Travelling"] },
{ name: "John", hobby: ["Reading", "Swimming"] },
{ name: "Rob", hobby: ["Running", "Coding"] },
];
function findSwimmers(members, hobby) {
let swimmers = [];
members.forEach(function (e){
e.hobby.forEach(function (element){
if (element.toLowerCase() === hobby.toLowerCase()) {
swimmers.push(e);
}
});
});
return swimmers;
}
Upvotes: 2
Views: 205
Reputation: 122916
First solution: bit of a hack but hey, no looping
Second solution: using Array.findIndex
may reduce the amount of iterations in the inner loop (well, at least gives you some probability of less iterations) because (MDN):
... If such an element is found, findIndex immediately returns the index for that iteration ...
const findMembersWithValueForKey = (members, key, value) =>
members.filter(member => member[key] instanceof Array
&& `#${member[key].join("#")}#`.toLowerCase()
.indexOf(`#${value.toLowerCase()}#`) > -1
|| false);
const findMembersWithValueForKey2 = (members, key, value) => {
value = value.toLowerCase();
return members.filter(member =>
member[key] instanceof Array
&& member[key].findIndex(v => v.toLowerCase() === value) > -1
|| false);
};
const members = [
{ name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
{ name: "Sam", hobby: ["Cars", "Travelling"] },
{ name: "John", hobby: ["Reading", "Swimming"] },
{ name: "Rob", hobby: ["Running", "Coding"] },
];
console.log(findMembersWithValueForKey(members, "hobby", "swimming"));
console.log(findMembersWithValueForKey2(members, "hobby", "swimming"));
Upvotes: 0
Reputation: 48367
You can use filter
in combination with some
by passing callback functions as argument.
let members = [
{ name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
{ name: "Sam", hobby: ["Cars", "Travelling"] },
{ name: "John", hobby: ["Reading", "Swimming"] },
{ name: "Rob", hobby: ["Running", "Coding"] },
];
function findSwimmers(members, hobby) {
return members_swimming = members.filter(({hobby}) => hobby.some(item => item == "Swimming"));
}
console.log(findSwimmers(members, "Swimming"));
Upvotes: 5
Reputation: 1074495
Any solution is going to involve loops. The only question is whether the loops are in your code or a function you call.
In your case, filter
and some
seem like the tools to use:
function findSwimmers(members, hobby) {
hobby = hobby.toLowerCase();
return members.filter(member =>
member.hobby.some(h => h.toLowerCase() === hobby)
);
}
You might want a different function name. :-)
Live Example:
const members = [
{ name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
{ name: "Sam", hobby: ["Cars", "Travelling"] },
{ name: "John", hobby: ["Reading", "Swimming"] },
{ name: "Rob", hobby: ["Running", "Coding"] },
];
function findSwimmers(members, hobby) {
hobby = hobby.toLowerCase();
return members.filter(member =>
member.hobby.some(h => h.toLowerCase() === hobby)
);
}
console.log(findSwimmers(members, "swimming"));
.as-console-wrapper {
max-height: 100% !important;
}
Note that your original code didn't stop looping when it found a hobby match (and if there were duplicate entries in the hobbies array, would have added the same member more than once — but presumably there aren't meant to be duplicates in that array).
You might also use String#localeCompare
, if available, with the sensitivity: "base"
option rather than comparing lower-case strings.
Upvotes: 1
Reputation: 30739
You can use Array.filter()
and Array.map()
with destructuring:
var members = [
{ name: "Sue", hobby: ["Swimming", "Running", "Dancing"] },
{ name: "Sam", hobby: ["Cars", "Travelling"] },
{ name: "John", hobby: ["Reading", "Swimming"] },
{ name: "Rob", hobby: ["Running", "Coding"] },
];
var swimmers = members.filter(({hobby}) => hobby.includes('Swimming')).map(({name}) => name);
console.log(swimmers)
Upvotes: 2
Reputation: 4107
You can achieve this with a single line:
let swimmers = members.filter(person => person.hobby.includes('Swimming'));
Upvotes: 0