Javascript найти дочерний объект во вложенных массивах
У меня есть структура javascript, как показано ниже (вложенные массивы объектов)
var categoryGroups = [
{
Id: 1, Categories: [
{ Id: 1 },
{ Id: 2 },
]
},
{
Id: 2, Categories: [
{ Id: 100 },
{ Id: 200 },
]
}
]
Я хочу найти дочерний объект Category, соответствующий идентификатору, при условии, что идентификатор категории уникален.
У меня есть это ниже, но было интересно, есть ли более сжатый способ сделать это:
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;
}
Ответы
Ответ 1
Предостережение: при этом используется пара функций Array.prototype
которые были добавлены только в ECMAScript 5, и, следовательно, не будут работать с более старыми браузерами, если вы не заполните их полностью.
Вы можете перебрать все объекты первого уровня в вашем массиве, а затем отфильтровать категории на основе вашего состояния и собрать все совпадения в массиве. Ваш окончательный результат будет первым элементом в массиве совпадений (совпадение не найдено, если массив пуст).
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/
Рекомендации:
Array.prototype.forEach
Array.prototype.concat
Array.prototype.filter
Ответ 2
проверьте код в 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);
Вышеприведенный код проверяет, найден ли в массиве id = 100. Если найденный будет предупреждать, что значение else предупреждает, что его не найдено. значение "100" было жестко запрограммировано для демонстрации
Ответ 3
Вы можете обернуть его внутри функции, чтобы избавиться от неудобного синтаксиса break;
, и вы можете загрузить каждый элемент в переменную внутри конструкции for(;;)
, чтобы сбрить несколько строк.
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);
Ответ 4
Простой способ использования lodash-библиотеки NodeJS (при условии, что вы используете 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
Ответ 5
Использование уменьшения и рекурсии:
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;
});
}
> попробуйте на JSFiddle
Ответ 6
Использование только Array.prototype.filter()
:
Если вы уверены, что искомый идентификатор существует, вы можете сделать следующее:
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];
Если вы не уверены, что он существует:
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
Ответ 7
Вы можете использовать underscore:
var cat = _(categoryGroups).
chain().
pluck('Categories').
flatten().
findWhere({Id: 2}).
value();
Что я делаю здесь, так это то, что я извлекаю все значения Categories
в одном массиве, а затем grepping для правильных категорий.
РЕДАКТИРОВАТЬ: извините, я не получил ваш вопрос в первый раз. Как следует из комментариев, вы можете не захотеть использовать подчеркивание только для этого, но так, как я это сделаю:)