javascript 递归迭代,将嵌套的子键替换为numeric

30byixjq  于 2023-03-28  发布在  Java
关注(0)|答案(3)|浏览(100)

需要你们的帮助
我有一个无限嵌套的嵌套对象。如何将children键重组为numeric键?
从这里:

{
  children: [
    {
      taskId: "e3f241f8-c879-4118-893d-a16715e45308",
      opts: {},
      children: [
        {
          taskId: "e3f241f8-c879-4118-893d-a248cae411208",
          opts: {},
          children: [
            taskId: "e3f241f8-c879-4118-89112d-s248cae411208",
            opts: {},
            children: []
          ]
        }
      ],
    }
  ],
}

对此:

{
  1: {
    2: {
      3: {
        4: ''
      }
    }
  }
}

我尝试使用forEach和递归函数,但没有任何结果。

tpxzln5u

tpxzln5u1#

不知道这个解释有多大意义,但是...这里的想法是循环遍历一个在你前进时构建的队列。队列中的项是旧的数据对象,引用一个在你前进时创建的新对象。一个数字在每次迭代中递增,作为新的键值。每次迭代,队列的一个成员被移除,并作为在当前对象有子对象时向队列添加更多项的基础。
下面的代码将沿树的水平方向(或广度优先/级别顺序遍历)对项进行编号:

const data = {
  children: [
    {
      taskId: "e3f241f8-c879-4118-893d-a16715e45308",
      opts: {},
      children: [
        {
          taskId: "e3f241f8-c879-4118-893d-a248cae411208",
          opts: {},
          children: [
            {
              taskId: "e3f241f8-c879-4118-89112d-s248cae411208",
              opts: {},
              children: []
            },
          ]
        },
        {
          taskId: "e3f241f8-c879-4118-893d-a248cae411208",
          opts: {},
          children: [
            {
              taskId: "e3f241f8-c879-4118-89112d-s248cae411208",
              opts: {},
              children: [
                {
                  children: []
                },
                {
                  children: []
                },
              ]
            },
          ]
        },
      ],
    }
  ],
};

const get_numeric_keys = (data) => {
  let number = 0;
  const result = {};
  const queue = [[data, result]];
  
  while(queue.length > 0) {
    const [obj, new_obj] = queue.shift();
    
    number++;
    new_obj[number] = obj?.children?.length > 0 ? {} : '';
    
    if(obj?.children?.length > 0) {
      queue.push(...obj.children.map( (child) => [child, new_obj[number]] ));
    }
  }
  
  return result;
};

console.log(get_numeric_keys(data));

这个版本通过尽可能先向下(或深度优先遍历)来对项目进行编号:

const data = {
  children: [
    {
      taskId: "e3f241f8-c879-4118-893d-a16715e45308",
      opts: {},
      children: [
        {
          taskId: "e3f241f8-c879-4118-893d-a248cae411208",
          opts: {},
          children: [
            {
              taskId: "e3f241f8-c879-4118-89112d-s248cae411208",
              opts: {},
              children: []
            },
          ]
        },
        {
          taskId: "e3f241f8-c879-4118-893d-a248cae411208",
          opts: {},
          children: [
            {
              taskId: "e3f241f8-c879-4118-89112d-s248cae411208",
              opts: {},
              children: [
                {
                  children: []
                },
                {
                  children: []
                },
              ]
            },
          ]
        },
      ],
    }
  ],
};

const get_numeric_keys = (data) => {
  let number = 0;
  const result = {};
  const queue = [[data, result]];
  
  while(queue.length > 0) {
    const [obj, new_obj] = queue.pop(); // pop instead of shift
    
    number++;
    new_obj[number] = obj?.children?.length > 0 ? {} : '';
    
    if(obj?.children?.length > 0) {
      // the new items go into the queue in reverse order here.
      queue.push(...obj.children.map( (child) => [child, new_obj[number]] ).reverse());
    }
  }
  
  return result;
};

console.log(get_numeric_keys(data));
des4xlb0

des4xlb02#

const data = {
  children: [{
    taskId: "e3f241f8-c879-4118-893d-a16715e45308",
    opts: {},
    children: [{
      taskId: "e3f241f8-c879-4118-893d-a248cae411208",
      opts: {},
      children: [{
        taskId: "e3f241f8-c879-4118-89112d-s248cae411208",
        opts: {},
        children: []
      }]
    }],
  }],
}

const result = replace(data)

console.log(result)

function replace(object, level = 1) {
  if (object !== undefined) {
    return {
      [level]: replace(object.children[0], level + 1)
    }
  }
  return ''
}
qij5mzcb

qij5mzcb3#

它似乎工作:我不知道为什么它会起作用,但我有一些要点(可能有助于解决问题):
1.确定何时停止递归
1.在TypeScript中思考确实有帮助
注:我不明白你的问题是什么:你想要什么样的遍历顺序?在BFS还是DFS中?我现在用DFS回答,因为你提到了“递归”。

// type ObjType = { children: [] | ObjType[]; };
const obj = {
  children: [
    {
      taskId: "e3f241f8-c879-4118-893d-a16715e45308",
      opts: {},
      children: [
        {
          taskId: "e3f241f8-c879-4118-893d-a248cae411208",
          opts: {},
          children: [
            { // [+] Curly Brackets
              taskId: "e3f241f8-c879-4118-89112d-s248cae411208",
              opts: {},
              children: []
            },
            {
              children: []
            }
          ]
        }
      ],
    },
    {
      children: [
        {
          children: []
        }
      ]
    }
  ],
};

// type MappedType = { [key: number]: string | MappedType; };
// {
//   1: {
//     2: {
//       3: {
//         4: ""
//       },
//       5: {
//         6: ""
//       }
//     }
//   },
//   7: {
//     8: {
//       9: ""
//     }
//   }
// }

// obj: ObjType, key is referenced
const mapper = (obj, key = [0]) => {
  key[0] += 1;
  const children = obj.children;
  if (children.length === 0) {
    return { [key[0]++]: '' };
  }

  // mapped: MappedType
  const mapped = {};
  for (const child of obj.children) {
    mapped[key[0]] = mapper(child, key); // key[0] is modified after returning
  }
  return mapped;
}

console.log(JSON.stringify(mapper(obj), undefined, 2));

相关问题