I have an array of objects created by constructor function. These objects have more key-value pairs then this example. But that's all working fine, so not relevant. Let's try to keep it concise :)
Example array:
let contactsArr = [
{id: 1, firstName: "Lucas", email: "lucas@fake.com"},
{id: 2, firstName: "Adrian", email: "adrian@fake.com"},
{id: 3, firstName: "Betrand", email: "zorro@fake.com"}
}
];
In the html, I have a search field #search
. You gessed it. This field is intended to search the array of contact objects for any matching values.
The content of this field is trimmed copied to an array of strings, divided by (1 ore more) spaces.
const $input = $("#search").val().toLowerCase().trim().split(/[\s]+/);
No problem there. For next step I wanted to find and return any values of the objects inside contactsArr
that are equal to (or contain part of) a string from $input
. First version, I came up with this code:
const filteredArr = contactsArr.filter(contact => {
return contact.firstName.toLowerCase().includes($input) ||
contact.email.toLowerCase().includes($input) ||
... // and more key-value pairs to check
});
That works fine when $input
returns a string, or an array with only 1 string. If the array contains more strings, only results for the first string will be searched and returned. But it's also a bit messy, considering the objects might have a lot more key-value pairs in the future. Hence version 2:
const filteredArr = contactsArr.filter(contact => {
return Object.values(contact).some(x => {
if (typeof x === "number") x = x.toString();
return x.toLowerCase().includes($input);
});
});
Version 2 returns exaclty the same result as version 1, only it works for a lot more key-value pairs then the ones listed inside the code. Great!! But when the $input
array has more then 1 value, the second value is still ignored. After lots of trail and error, I hope someone can point out my mistake.
This is version 3: (or maybe even 33) :)
const filteredArr = contactsArr.filter(contact => {
return Object.values(contact).some(x => {
// contact.id number to string
if (typeof x === "number") x = x.toString();
// match with lowercase (same as $input)
x = x.toLocaleLowerCase();
// check if includes and return true or false
return $input.some(word => x.includes(word));
});
});
Expected result: The aim is to have all the contacts that match any of the strings in $input
.
Many thanks for any and all tips and insights!