【问题标题】:How to recursively map/restructure an object?如何递归地映射/重构对象?
【发布时间】:2022-01-03 16:41:38
【问题描述】:

我想要一个对象数组,其中包含来自嵌套对象的所有对象键。我编写了一个递归函数来执行此操作,但是在调用该函数时,它并没有按预期通过对象,而是无限地发回一个索引。

let array = [];

const findKeys = (ob) => {
  let id = 0;
  let keys = Object.keys(ob);
  for (let i = 0; i < keys.length; i++) {

    let object = {
      id: id,
      label: keys[i],
    };

    array.push(object);
    id ++;
    findKeys(ob[keys[i]]);
  }
  return array;
};
let newArray = findKeys(data);
console.log(newArray);

示例数据结构:

const data = {a: {
  b: {
    c: {
      foo: 'bar'
    }
  }
}}

【问题讨论】:

  • 你的data看起来怎么样?
  • 在调用 findKeys 之前没有检查它是否是一个对象似乎很奇怪
  • 按照您的编码方式,您将在数组中拥有多个具有相同 id 的元素,因为您不断将 id 重置为零。 .
  • 数据是一个包含对象的对象
  • 你能提供你的预期结果吗

标签: javascript arrays function object recursion


【解决方案1】:

在进行下一次递归调用之前,您需要检查是否有对象。您还正在重置 id,因此您将要重复 id(也许您想要那个?)并且您正在为数组使用全局,因此它不能多次使用。

你会想要这样的东西:

function getKeys(obj) {

  const array = [];
  let id = 0;

  function loop(obj) {
    Object.entries(obj).forEach(entry => {
      array.push({
        id: ++id,
        label: entry[0],
      });      
      if(entry[1] != null && entry[1].constructor.name === "Object") {
        loop(entry[1]);
      }
    });
  }

  loop(obj);

  return array;
}

const obj1 = { a: 1, b: 'bar' };
console.log(getKeys(obj1));

const obj2 = { a: 1, b: { c: 'bar' } };
console.log(getKeys(obj2));

【讨论】:

    【解决方案2】:

    类似的东西

    另见Check that value is object literal?

    const data = { a: { b: { c: { foo: 'bar' } } }}
    
    const isObject = el => (Object.prototype.toString.call(el) === '[object Object]')
    
    const findKeys = obj => 
      {
      let arr   = []
        , id    = 0
        ;
      getKeys(obj)
      return arr
    
      function getKeys(o)
        {
        Object.keys(o).forEach(key =>
          { 
          arr.push({ id:id++, label:key })
          if (isObject(o[key]))
            getKeys(o[key])
          })  
        }
      }
      
    
    console.log( findKeys(data) )
    .as-console-wrapper {max-height: 100%!important;top:0 }

    【讨论】:

      【解决方案3】:

      也许你会喜欢

      var data = {a: {
        b: {
          c: {
            foo: 'bar',
            arr: [1,2,3,4]
          }
        }
      }};
      
      function getAllKeys(obj){
        var keys = (typeof obj === "object") && (obj !== null) && Object.keys(obj);
        return !!keys ? keys.reduce((r,k) => r.concat(getAllKeys(obj[k])),keys)
                      : [];
      };
      
      var res = getAllKeys(data);
      
      console.log(JSON.stringify(res));

      【讨论】:

        【解决方案4】:

        这是一个简单的技术,使用相当通用的深度优先键收集遍历,然后是添加索引的映射:

        const flattenKeys = (o) =>
          Object (o) === o
            ? Object .entries (o) .flatMap (([k, v]) => [k, ...flattenKeys (v)])
            : []
        
        const getKeys = (o) =>
          flattenKeys (o) .map ((label, id) => ({label, id}))
        
        const data = {a: {b: {c: {foo: 'bar'}}}}
        
        console .log (getKeys (data))
        .as-console-wrapper {max-height: 100% !important; top: 0}

        如果您想要广度优先遍历,它不会更难。

        密钥收集和索引生成的这种分离使我认为代码更简单。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-10-11
          • 1970-01-01
          • 1970-01-01
          • 2020-09-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多