Reputation: 129
Suppose I have object
let x = { "people" :{
"Sally": "value",
"Bob" : "other value"
},
"cars" :{
"Saab" : "this",
"Chevy": "that"
},
"trees":{
"Birch" : "what",
"Oak" : "where"
}
}
I want to search, so if I searched for "S" I'd get back an array that was
{ "people" :{
"Sally": "value",
},
"cars" :{
"Saab" : "this",
}
}
And if I searched for "b" I'd get:
{ "people" :{
"Bob" : "other value"
},
"trees":{
"Birch" : "what",
}
}
or "bo" would return
{ "people" :{
"Bob" : "other value"
}
And if I searched "e" I'd get
{ "cars" :{
"Chevy": "that"
}
}
Note that the "people" and "trees" isn't caught by the search for 'e'.
The strut will be of a fixed depth, and we only ever want to catch keys that match the filter and don't have children (we're also not interested in values that match, just keys).
Adding npm dependencies is acceptable.
Attempted solution:
filteredList(unfiltered,searchVal) {
return unfiltered.filter(search=> {
return search.toLowerCase().includes(searchVal.toLowerCase())
})
}
Obviously there's more to it, but I'm not sure which direction to proceed.
Upvotes: 3
Views: 85
Reputation: 2401
This is a basic attempt. It's seems work quite fine but I'm very sure that it may be possible to make even better. But I don't know how.
let x = {
"people": {
"Sally": "value",
"Bob": "other value"
},
"cars": {
"Saab": "this",
"Chevy": "that"
},
"trees": {
"Birch": "what",
"Oak": "where"
}
}
let search = "B";
let result = {};
for (let key in x) {
let tmp = {};
for (let subKey in x[key]) {
if (subKey.includes(search)) { // Use startsWithif you want even substring that aren't at the beginning
tmp[subKey] = x[key][subKey];
}
if (Object.keys(tmp).length > 0) {
result[key] = Object.assign({}, tmp);
}
}
}
console.log(result)
If you want an arbitrary deep, you should try with some kind of recursion, but that will be more complex.
Upvotes: 4
Reputation: 32176
Here's a solution that uses the lodash library. Lodash has a number of super useful methods for object manipulation, in this case _.pickBy
and _.mapValues
can be used to filter your nested object.
Example:
let x = {
"people": {
"Sally": "value",
"Bob": "other value"
},
"cars": {
"Saab": "this",
"Chevy": "that"
},
"trees": {
"Birch": "what",
"Oak": "where"
}
}
function search(query) {
query = query.toLowerCase();
const matched = _.mapValues(x, v => _.pickBy(v, (_, k) => k.toLowerCase().includes(query)));
return _.pickBy(matched, v => Object.keys(v).length)
}
console.log(search("S"))
console.log(search("b"))
console.log(search("bo"))
console.log(search("e"))
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
Upvotes: 1