Поиск свойств lodash в массиве и вложенных дочерних массивах
У меня есть этот массив:
[
{
id: 1,
name: 'test 1',
children: []
},
{
id: 2,
name: 'test 2',
children: [
{
id: 4,
name: 'test 4'
}
]
},
{
id: 3,
name: 'test 3',
children: []
}
]
Как фильтровать свойство id
как в этом массиве, так и вложенных массивах children
?
Например, поиск id = 3
должен вернуть объект test 3
, и поиск id = 4
должен вернуть объект test 4
.
Ответы
Ответ 1
Используя lodash, вы можете сделать что-то вроде этого:
_(data)
.thru(function(coll) {
return _.union(coll, _.pluck(coll, 'children'));
})
.flatten()
.find({ id: 4 });
Здесь thru() используется для инициализации обернутого значения. Он возвращает объединение исходного массива и вложенных дочерних элементов. Эта структура массива затем сглаживается с помощью flatten(), поэтому вы можете найти() элемент.
Ответ 2
Это очень простая задача обход дерева. Самый простой способ решить это рекурсия (ссылка на jsbin). Он будет работать с любой глубиной (с пределом рекурсии, конечно), и это один из самых быстрых способов с наихудшей сложностью O (n):
function find(id, items) {
var i = 0, found;
for (; i < items.length; i++) {
if (items[i].id === id) {
return items[i];
} else if (_.isArray(items[i].children)) {
found = find(id, items[i].children);
if (found) {
return found;
}
}
}
}
Обновление:
Чтобы найти все совпадения - слегка измененная функция (ссылка jsbin выше обновлена):
function findAll(id, items) {
var i = 0, found, result = [];
for (; i < items.length; i++) {
if (items[i].id === id) {
result.push(items[i]);
} else if (_.isArray(items[i].children)) {
found = findAll(id, items[i].children);
if (found.length) {
result = result.concat(found);
}
}
}
return result;
}
Ответ 3
Еще одна опция lodash
с ключевым словом для детей и неограниченным уровнем.
const flattenItems = (items, key) => {
return items.reduce((flattenedItems, item) => {
flattenedItems.push(item)
if (Array.isArray(item[key])) {
flattenedItems = flattenedItems.concat(flattenItems(item[key], key))
}
return flattenedItems
}, [])
}
const item = find(flattenItems(items, 'children'), ['id', 4])