cup*_*_of 13 javascript arrays function object ecmascript-6
如何在深层嵌套对象中按特定键查找所有值?
例如,如果我有一个这样的对象:
const myObj = {
id: 1,
children: [
{
id: 2,
children: [
{
id: 3
}
]
},
{
id: 4,
children: [
{
id: 5,
children: [
{
id: 6,
children: [
{
id: 7,
}
]
}
]
}
]
},
]
}
Run Code Online (Sandbox Code Playgroud)
我将如何通过id.
注意:children是一个一致的名称,并且id's 不会存在于children对象之外。
所以从 obj 中,我想生成一个这样的数组:
const idArray = [1, 2, 3, 4, 5, 6, 7]
Run Code Online (Sandbox Code Playgroud)
Ste*_*ado 16
这有点晚了,但对于其他发现此问题的人,这是一个干净的通用递归函数:
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')
Run Code Online (Sandbox Code Playgroud)
zma*_*mag 10
你可以做一个这样的递归函数:
idArray = []
function func(obj) {
idArray.push(obj.id)
if (!obj.children) {
return
}
obj.children.forEach(child => func(child))
}
Run Code Online (Sandbox Code Playgroud)
您的示例的代码段:
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)Run Code Online (Sandbox Code Playgroud)
我发现史蒂夫的答案最适合我推断并创建通用递归函数的需求。也就是说,我在处理空值和未定义值时遇到了问题,因此我扩展了条件以适应这种情况。该方法使用:
Array.reduce() - 它使用累加器函数将值附加到结果数组上。它还将每个对象拆分为其键:值对,这允许您执行以下步骤:
希望能帮助到你!
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)Run Code Online (Sandbox Code Playgroud)
您可以创建一个适用于任何属性和任何对象的通用递归函数。
此用途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));Run Code Online (Sandbox Code Playgroud)
注意:
children是一个一致的名称,并且id's 不会存在于children对象之外。所以从 obj 中,我想生成一个这样的数组:
Run Code Online (Sandbox Code Playgroud)const idArray = [1, 2, 3, 4, 5, 6, 7]
鉴于该问题不包含对如何从输入导出输出的任何限制,并且输入是一致的,其中属性的值"id"是一个数字并且id属性仅在"children"属性中定义,除了"id"对象中的第一个的情况, 输入的 JavaScript 纯对象可以JSON使用JSON.stringify(),RegExp /"id":\d+/g匹配"id"属性和属性名称后的一个或多个数字字符转换为字符串,然后映射到.match()前一个匹配的数字部分,Regexp \d+并将数组值转换为 JavaScript 数字使用加法运算符+
const idArray = [1, 2, 3, 4, 5, 6, 7]
Run Code Online (Sandbox Code Playgroud)
JSON.stringify() replacer函数也可以用于将对象内.push()每个"id"属性名称的值转换为数组
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);Run Code Online (Sandbox Code Playgroud)
由于要匹配的输入的属性值是数字,所以所有的JavaScript对象都可以转换为字符串,RegExp \D可以用来替换所有不是数字的字符,将结果字符串扩展到数组,将.map()数字扩展到JavaScript数字
let res = [...JSON.stringify(myObj).replace(/\D/g,"")].map(Number)
Run Code Online (Sandbox Code Playgroud)