Извлечь глубоко вложенные дочерние объекты по имени свойства с помощью lodash
У меня есть массивы глубоко вложенных объектов. Я хотел бы написать функцию для извлечения произвольных дочерних объектов из этих массивов. В некоторых случаях значения вложенных свойств являются значениями и объектами, в других случаях они являются массивами.
Примеры массивов ниже:
[{parent: {level1: {level2: 'data'}}}]
[{parent: {level1: [{level2: {...}}, {level2: {...}}, {level2: {...}}]}}]
[{parent: {level1: [{level2: {level3: 'data'}}, {level2: {..}}, {level2: {..}}]}}]
Вызов функции извлечения на таком массиве должен привести к массиву объектов, которые нас интересуют.
Примеры вызова функции и ее результатов для приведенных выше массивов примеров:
extractChildren(source, 'level2') = [{level2: 'data'}]
extractChildren(source, 'level2') = [{level2: {...}, level2: {...}, level2: {...}]
extractChildren(source, 'level3') = [{level3: 'data'}]
Есть ли сжатый способ достичь этого с помощью lodash
или я должен использовать обычный JavaScript для итерации через свойства?
P.S. Подумайте об этом как эквивалент XPath select all nodes with the name "nodename"
Ответы
Ответ 1
Надеюсь, это поможет:
'use strict';
let _ = require("lodash");
let source = [{parent: {level1: [{level2: {level3: 'data'}}, {level2: {}}, {level2: {}}]}}];
function extractChildren(source, specKey) {
let results = [];
let search = function(source, specKey) {
_.forEach(source, function(item) {
if (!!item[specKey]) {
let obj = {};
obj[specKey] = item[specKey];
results.push(obj);
return;
}
search(item, specKey);
});
};
search(source, specKey);
return results;
};
console.log(extractChildren(source, 'level3'));
// [ { level3: 'data' } ]
Ответ 2
Из этот вопрос:
Elegant:
function find_obj_by_name(obj, key) {
if( !(obj instanceof Array) ) return [];
if (key in obj)
return [obj[key]];
return _.flatten(_.map(obj, function(v) {
return typeof v == "object" ? find_obj_by_name(v, key) : [];
}), true);
}
Эффективность:
function find_obj_by_name(obj, key) {
if( !(obj instanceof Array) ) return [];
if (key in obj)
return [obj[key]];
var res = [];
_.forEach(obj, function(v) {
if (typeof v == "object" && (v = find_obj_by_name(v, key)).length)
res.push.apply(res, v);
});
return res;
}