如何在深层嵌套对象中按特定键查找所有值?
例如,如果我有一个像这样的对象:
const myObj = {
id: 1,
children: [
{
id: 2,
children: [
{
id: 3
}
]
},
{
id: 4,
children: [
{
id: 5,
children: [
{
id: 6,
children: [
{
id: 7,
}
]
}
]
}
]
},
]
}
如何通过id
的键来获取此obj所有嵌套中所有值的数组。
注意:children
是一致的名称,id
不会存在于children
对象之外。
因此,从obj,我想产生一个像这样的数组:
const idArray = [1, 2, 3, 4, 5, 6, 7]
谢谢!
答案 0 :(得分:3)
使用递归。
const myObj = { id: 1, children: [ { id: 2, children: [ { id: 3 } ] }, { id: 4, children: [ { id: 5, children: [ { id: 6, children: [ { id: 7, } ] } ] } ] }, ]},
loop = (array, key, obj) => {
if (!obj.children) return;
obj.children.forEach(c => {
if (c[key]) array.push(c[key]); // is not present, skip!
loop(array, key, c);
});
},
arr = myObj["id"] ? [myObj["id"]] : [];
loop(arr, "id", myObj);
console.log(arr);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:3)
您可以创建一个通用的递归函数,该函数可与任何属性和任何对象一起使用。
这使用Object.entries()
,Object.keys()
,Array.reduce()
,Array.isArray()
,Array.map()
和Array.flat()
。
停止条件是传入的对象为空时
const myObj = {
id: 1,
anyProp: [{
id: 2,
thing: { a: 1, id: 10 },
children: [{ id: 3 }]
}, {
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{ id: 7 }]
}]
}]
}]
};
const getValues = prop => obj => {
if (!Object.keys(obj).length) { return []; }
return Object.entries(obj).reduce((acc, [key, val]) => {
if (key === prop) {
acc.push(val);
} else {
acc.push(Array.isArray(val) ? val.map(getIds).flat() : getIds(val));
}
return acc.flat();
}, []);
}
const getIds = getValues('id');
console.log(getIds(myObj));
答案 2 :(得分:2)
您可以使用Object.entries
来创建递归函数,如下所示:
const myObj = {
id: 1,
children: [{
id: 2,
children: [{
id: 3
}]
},
{
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{
id: 7,
}]
}]
}]
},
]
};
function findIds(obj) {
const entries = Object.entries(obj);
let result = entries.map(e => {
if (e[0] == "children") {
return e[1].map(child => findIds(child));
} else {
return e[1];
}
});
function flatten(arr, flat = []) {
for (let i = 0, length = arr.length; i < length; i++) {
const value = arr[i];
if (Array.isArray(value)) {
flatten(value, flat);
} else {
flat.push(value);
}
}
return flat;
}
return flatten(result);
}
var ids = findIds(myObj);
console.log(ids);
this answer中的平整功能
ES5语法:
var myObj = {
id: 1,
children: [{
id: 2,
children: [{
id: 3
}]
},
{
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{
id: 7,
}]
}]
}]
},
]
};
function findIds(obj) {
const entries = Object.entries(obj);
let result = entries.map(function(e) {
if (e[0] == "children") {
return e[1].map(function(child) {
return findIds(child)
});
} else {
return e[1];
}
});
function flatten(arr, flat = []) {
for (let i = 0, length = arr.length; i < length; i++) {
const value = arr[i];
if (Array.isArray(value)) {
flatten(value, flat);
} else {
flat.push(value);
}
}
return flat;
}
return flatten(result);
}
var ids = findIds(myObj);
console.log(ids);
答案 3 :(得分:1)
您可以像这样创建一个递归函数:
idArray = []
function func(obj) {
idArray.push(obj.id)
if (!obj.children) {
return
}
obj.children.forEach(child => func(child))
}
样本片段:
const myObj = {
id: 1,
children: [{
id: 2,
children: [{
id: 3
}]
},
{
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{
id: 7,
}]
}]
}]
},
]
}
idArray = []
function func(obj) {
idArray.push(obj.id)
if (!obj.children) {
return
}
obj.children.forEach(child => func(child))
}
func(myObj)
console.log(idArray)
答案 4 :(得分:1)
注意:
children
是一致的名称,id
不会存在于外部children
对象。因此,从obj,我想产生一个像这样的数组:
const idArray = [1, 2, 3, 4, 5, 6, 7]
鉴于问题不包含任何关于如何从输入派生输出的限制,并且输入是一致的,其中属性"id"
的值是一个数字,并且定义了id
属性仅在"children"
属性中,除了对象中第一个"id"
的情况外,输入的JavaScript纯对象可以使用JSON
,{{1 }} JSON.stringify()
匹配RegExp
属性和该属性名称后的一个或多个数字字符,然后使用/"id":\d+/g
将其映射到"id"
上一个匹配项的数字部分{ {1}}并使用加法运算符.match()
Regexp
\d+
+
函数可用于将对象内每个const myObject = {"id":1,"children":[{"id":2,"children":[{"id":3}]},{"id":4,"children":[{"id":5,"children":[{"id":6,"children":[{"id":7}]}]}]}]};
let res = JSON.stringify(myObject).match(/"id":\d+/g).map(m => +m.match(/\d+/));
console.log(res);
属性名的值JSON.stringify()
到数组中
replacer
由于要匹配的输入的属性值是数字,因此所有JavaScript对象都可以转换为字符串,并且.push()
"id"
可用于替换所有非数字字符结果字符串到数组,const myObject = {"id":1,"children":[{"id":2,"children":[{"id":3}]},{"id":4,"children":[{"id":5,"children":[{"id":6,"children":[{"id":7}]}]}]}]};
const getPropValues = (o, prop) =>
(res => (JSON.stringify(o, (key, value) =>
(key === prop && res.push(value), value)), res))([]);
let res = getPropValues(myObject, "id");
console.log(res);
位数字到JavaScript数字
RegExp
答案 5 :(得分:1)
这有点晚了,但是对于其他任何人,这是一个干净的,通用的递归函数:
function findAllByKey(obj, keyToFind) {
return Object.entries(obj)
.reduce((acc, [key, value]) => (key === keyToFind)
? acc.concat(value)
: (typeof value === 'object')
? acc.concat(findAllByKey(value, keyToFind))
: acc
, [])
}
// USAGE
findAllByKey(myObj, 'id')
答案 6 :(得分:1)
我发现史蒂夫的答案最适合我的需求,可以对此进行推断并创建通用的递归函数。就是说,在处理null和未定义的值时遇到了问题,因此我扩展了条件以适应这种情况。这种方法使用:
Array.reduce()-它使用一个累加器函数,该函数将值的值附加到结果数组上。还将每个对象分成其key:value对,使您可以执行以下步骤:
希望有帮助!
const myObj = {
id: 1,
children: [{
id: 2,
children: [{
id: 3
}]
},
{
id: 4,
children: [{
id: 5,
children: [{
id: 6,
children: [{
id: 7,
}]
}]
}]
},
]
}
function findAllByKey(obj, keyToFind) {
return Object.entries(obj)
.reduce((acc, [key, value]) => (key === keyToFind)
? acc.concat(value)
: (typeof value === 'object' && value)
? acc.concat(findAllByKey(value, keyToFind))
: acc
, []) || [];
}
const ids = findAllByKey(myObj, 'id');
console.log(ids)
答案 7 :(得分:0)
我们现在将object-scan用于很多数据处理需求。它使代码更易于维护,但是花了一点时间。这是您如何使用它来回答您的问题
const objectScan = require('object-scan');
const find = (data, needle) => objectScan([needle], { rtn: 'value' })(data);
const myObj = {
id: 1,
children: [{
id: 2,
children: [
{ id: 3 }
]
}, {
id: 4,
children: [
{
id: 5,
children: [
{
id: 6,
children: [
{ id: 7 }
]
}
]
}
]
}]
};
console.log(find(myObj, '**.id'));
// => [ 7, 6, 5, 4, 3, 2, 1 ]
答案 8 :(得分:0)
import {flattenDeep} from 'lodash';
/**
* Extracts all values from an object (also nested objects)
* into a single array
*
* @param obj
* @returns
*
* @example
* const test = {
* alpha: 'foo',
* beta: {
* gamma: 'bar',
* lambda: 'baz'
* }
* }
*
* objectFlatten(test) // ['foo', 'bar', 'baz']
*/
export function objectFlatten(obj: {}) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(objectFlatten(value));
} else {
result.push(value);
}
}
return flattenDeep(result);
}