在深层嵌套对象中按特定键查找所有值

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)

  • 超级干净,效果很好,易于剪切和粘贴。最佳答案。 (2认同)

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)


Raa*_*ode 9

我发现史蒂夫的答案最适合我推断并创建通用递归函数的需求。也就是说,我在处理空值和未定义值时遇到了问题,因此我扩展了条件以适应这种情况。该方法使用:

Array.reduce() - 它使用累加器函数将值附加到结果数组上。它还将每个对象拆分为其键:值对,这允许您执行以下步骤:

  1. 你找到钥匙了吗?如果有,则将其添加到数组中;
  2. 如果没有,我是否找到了具有值的对象?如果是这样,钥匙可能就在那里。通过调用该对象上的函数继续挖掘并将结果附加到结果数组中;和
  3. 最后,如果这不是一个对象,则返回结果数组不变。

希望能帮助到你!

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)


jo_*_*_va 5

您可以创建一个适用于任何属性和任何对象的通用递归函数。

此用途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)


gue*_*314 5

注意:children是一个一致的名称,并且id's 不会存在于children对象之外。

所以从 obj 中,我想生成一个这样的数组:

const idArray = [1, 2, 3, 4, 5, 6, 7]
Run Code Online (Sandbox Code Playgroud)

鉴于该问题不包含对如何从输入导出输出的任何限制,并且输入是一致的,其中属性的值"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)