Reputation: 19967
In the below method,
self.search = (obj, search) => {
...
the second argument, search
is an array of search strings. The first is an object.
The algorithm is to be used in a filter
method that returns true
if an object contains any of the search strings.
self.search = (obj, search) => {
return Object.keys(obj).some(k =>
typeof obj[k] === 'object'
? self.search(obj[k], search)
: search.some(v => String(obj[k]).includes(v))
)
}
So, for example, given the following object:
{
name: 'Peter',
phone: {
primary: 5556667777,
mobile: 1112223333
}
}
self.search
would return true for the following values of the search
argument:
['Pet']
['Pet', '111']
['Pet', 'asdf']
The Question
How can self.search
be changed to instead return true only if each element of the search
array is contained by the object?
Essentially, ['Pet', 'asdf']
should return false
.
Update
Replacing some
with every
does not work when the array of search strings is across levels.
// `['Pet']` correctly returns true
// `['Pet', '111']` returns false when it should return true
// `['Pet', 'asdf']` correctly returns false
self.search = (obj, search) => {
return Object.keys(obj).some(k =>
typeof obj[k] === 'object'
? self.search(obj[k], search)
: search.every(v => String(obj[k]).toLowerCase().includes(v))
)
}
Upvotes: 1
Views: 84
Reputation: 386560
You could use your single search function and a meta seach for every single item of the array.
var search = (obj, v) => Object.keys(obj).some(k => typeof obj[k] === 'object' ? search(obj[k], v) : obj[k].toString().includes(v)),
findAll = (obj, array) => array.every(a => search(obj, a)),
obj = { name: 'Peter', phone: { primary: 5556667777, mobile: 1112223333 } };
console.log(findAll(obj, ['Pet', '99'])); // false
console.log(findAll(obj, ['Pet'])); // true
console.log(findAll(obj, ['Pet', '111'])); // true
console.log(findAll(obj, ['Pet', 'asdf'])); // false
Upvotes: 3