Reputation: 1791
I have the following object:
const obj = {
alphas: {
top: [{name: "q"}, {name: "w"}],
middle: [{name: "a"}, {name: "s"}],
bottom: [{name: "z"}, {name: "x"}],
},
numbers: {
low: [{name: "1"}, {name: "2"}, {name: "3"}],
high: [{name: "1000"}, {name: "2000"}],
}
}
I need the nested indexes of the name
.
For instance, if I'm looking for "s"
the result should be the array [0, 1]
:
0
because "s"
is in the first category (alphas
)1
because "s"
is in the second subcategory (middle
).I'm able to find the indexes in separate loops:
const categoryIndex = Object.keys(obj).findIndex(
cat => Object.keys(obj[cat]).some(
subcat => obj[cat][subcat].some(
key => key.name === "s")));
const categoryName = Object.keys(obj)[categoryIndex];
const subcategoryIndex = Object.keys(obj[categoryName]).findIndex(
subcat => obj[categoryName][subcat].some(key => key.name === "s"));
const result = [categoryIndex, subcategoryIndex];
https://jsfiddle.net/7w523ojn/
Having two separate loops may cost too much so I'm looking for a way to get indexes at once. Something like this:
[categoryIndex , subcategoryIndex] = ...
Is there a way to get nested indexes at once? Solutions involving Lodash, Ramda and whatnot are also welcome. Thank you.
Upvotes: 1
Views: 259
Reputation: 30370
If I understand you question correctly, then this can be achieve via a recursive search and return function, as detailed below:
const obj={alphas:{top:[{name:"q"},{name:"w"}],middle:[{name:"a"},{name:"s"}],bottom:[{name:"z"},{name:"x"}]},numbers:{low:[{name:"1"},{name:"2"},{name:"3"}],high:[{name:"1000"},{name:"2000"}]}};
const recursiveSearch = (object, searchFor) => {
let index = 0;
for (const key in object) {
const value = object[key];
if (Array.isArray(value)) {
/* If object value is an array, iterate through it and
search for item with name field matching searchFor
character */
const array = value;
for (let i = 0; i < array.length; i++) {
/* If array item's name matches searchFor charater
then return this as the first entry in our results
array */
if (array[i].name === searchFor) {
return [index, i];
}
}
} else if (typeof object === "object") {
/* If object value is object, then recursivly search
through children for a result. If an result is found,
prepend the current key's index to the result array */
const result = recursiveSearch(value, searchFor);
/* Array.isArray() tells us this call to recursiveSearch()
found a result, so we are to return from this call */
if (Array.isArray(result)) {
return [index].concat(result);
}
}
index++;
}
};
console.log('indicies for "s":', recursiveSearch(obj, 's'));
Upvotes: 1