Javascript find child in nested arrays

I have a javascript structure as shown below (nested arrays of objects)

var categoryGroups = [ { Id: 1, Categories: [ { Id: 1 }, { Id: 2 }, ] }, { Id: 2, Categories: [ { Id: 100 }, { Id: 200 }, ] } ] 

I want to find the Category child of the identifier, provided that the category identifier is unique.

I have this below, but was wondering if there is a more concise way to do this:

 var category, categoryGroup, found = false; for (i = 0; i < categoryGroups.length ; i++) { categoryGroup = categoryGroups[i]; for (j = 0; j < categoryGroup.Categories.length; j++) { category = categoryGroup.Categories[j]; if (category.Id === id) { found = true; break; } } if (found) break; } 
+10
source share
7 answers

Caution : this uses a couple of Array.prototype functions that were added only in ECMAScript 5, and therefore will not work with older browsers if you do not fill them out completely.

You can iterate over all the first level objects in your array, and then filter the categories based on your state and collect all matches in the array. Your final result will be the first element in the array of matches (no match found if the array is empty).

 var matches = []; var needle = 100; // what to look for arr.forEach(function(e) { matches = matches.concat(e.Categories.filter(function(c) { return (c.Id === needle); })); }); console.log(matches[0] || "Not found"); 

JSFiddle: http://jsfiddle.net/b7ktf/1/

Recommendations :

Array.prototype.forEach
Array.prototype.concat
Array.prototype.filter

+8
source

check the code in fiddle

 var categoryGroups = [ { Id: 1, Categories: [ { Id: 1 }, { Id: 2 }, ] }, { Id: 2, Categories: [ { Id: 100 }, { Id: 200 }, ] } ] var id = 100; var x = 'not found'; var category, categoryGroup, found = false; for (i = 0; i < categoryGroups.length ; i++) { categoryGroup = categoryGroups[i]; for (j = 0; j < categoryGroup.Categories.length; j++) { category = categoryGroup.Categories[j]; if (category.Id == id) { var x = category.Id; found = true; break; } } if (found) break; } alert(x); 

The above code checks to see if id = 100 is found in the array. If found, it will warn that the else value warns that it is not found. the value "100" was hard-coded to demonstrate

+1
source

You can wrap it inside a function to get rid of the inconvenient break; syntax break; , and you can load each element into a variable inside the for(;;) construct to shave several lines.

 function subCategoryExists(groups, id) { for (var i = 0, group; group = groups[i]; ++i) { for (var k = 0, category; category = group.Categories[k]; ++k) { if (category.Id == id) { return true; } } } return false; } var found = subCategoryExists(categoryGroups, 100); 
+1
source

A simple way to use the NodeJS lodash library (assuming you are using NodeJS):

 const _ = require('lodash'); let category ; let categoryGroup = _.find(categoryGroups, (element)=>{ category = _.find(element.Categories, {Id : 100}); return category; }); console.log(categoryGroup); // The category group which has the sub category you are looking for console.log(category); // The exact category you are looking for 
+1
source

Using reduction and recursion:

 function nestedSearch(value) { return categoryGroups.reduce(function f(acc, val) { return (val.Id === value) ? val : (val.Categories && val.Categories.length) ? val.Categories.reduce(f, acc) : acc; }); } 

> try on JSFiddle

+1
source

Using only Array.prototype.filter() :

If you are sure that the identifier you are looking for exists, you can do the following:

 var id = 200; // surely it exists var category = arr.filter(g => g.Categories.filter(c => c.Id === id)[0])[0].Categories.filter(c => c.Id === id)[0]; 

If you are not sure if it exists:

 var id = 201; // maybe it does not exist var categoryGroup = arr.filter(e => e.Categories.filter(c => c.Id === id)[0])[0]; var category = categoryGroup ? categoryGroup.Categories.filter(c => c.Id === id)[0] : null; 

jsfiddle

+1
source

You can use underscore :

 var cat = _(categoryGroups). chain(). pluck('Categories'). flatten(). findWhere({Id: 2}). value(); 

What I'm doing here is that I retrieve all the Category values ​​in one array, and then grepping for the correct categories.

EDIT : Sorry, I did not receive your question for the first time. As the comments suggest, you may not want to use underlining just for this, but the way I do it :)

0
source

All Articles