在深度嵌套的对象数组中查找最大 id 值

Find maximum id value in a deeply nested array of objects

我有一个树数据结构,每个对象都包含子对象:

const data = {
  id: 1,
  name: "John",
  parent_id: null,
  children: [{
      id: 2,
      name: "Tess",
      parent_id: 1,
      children: []
    },
    {
      id: 3,
      name: "Tom",
      parent_id: 1,
      children: [{
          id: 4,
          name: "Harry",
          parent_id: 3,
          children: [{
            id: 7,
            name: "Thabo",
            parent_id: 4,
            children: []
          }]
        },
        {
          id: 5,
          name: "Mary",
          parent_id: 3,
          children: []
        },
        {
          id: 6,
          name: "Madge",
          parent_id: 3,
          children: []
        }
      ]
    }
  ]
}

在向树中添加新对象之前,我需要确定当前使用的最高 id 值,以便为新用户分配下一个可用编号 id

为此,我创建了一个初始值为 0 的新变量。然后我遍历树中的每个对象,如果对象的 id 高于新的 id,我将新的分配给id 当前 id 的值(想法是取最终值并加 1 以获得新 id)。

let newUserID = 0;
const newID = ( root, idKey ) => {
  if ( root.id > idKey ) {
    idKey = root.id;
  }
  root.children.forEach( ( obj ) => {
    newID( obj, idKey );
  });
  return idKey;
}

newUserID = newID( data, newUserID );

console.log( newUserID );

我希望这个 return 树中最高的 id 作为最终值,但实际发生的是,虽然新的 id 确实增加直到它匹配最大值,但它然后再次开始减少,以 1 结束。

这可以在这个 JSFiddle 中看到,其中包括一些日志记录以显示函数中不同点的新 ID 的值。

我已经使用不同的方法解决了这个问题(将 id 值提取到一个新数组,并使用 Math.max() 找到最大值),但我想理解为什么我最初的方法没有按预期工作。我可以看到 idKey 值正在更新,但之前的值在递归调用中被传回,但我不知道为什么会这样或如何防止它。

你可以使用递归来解决这个问题。喜欢下面

const data = {
  id: 1,
  name: "John",
  parent_id: null,
  children: [
    {
      id: 2,
      name: "Tess",
      parent_id: 1,
      children: [],
    },
    {
      id: 3,
      name: "Tom",
      parent_id: 1,
      children: [
        {
          id: 4,
          name: "Harry",
          parent_id: 3,
          children: [
            {
              id: 7,
              name: "Thabo",
              parent_id: 4,
              children: [],
            },
          ],
        },
        {
          id: 5,
          name: "Mary",
          parent_id: 3,
          children: [],
        },
        {
          id: 6,
          name: "Madge",
          parent_id: 3,
          children: [],
        },
      ],
    },
  ],
};

const findMax = (value) => {
  let max = -Infinity;
  const _findMax = (data) => {
    if (max < data.id) max = data.id;
    data.children.forEach(_findMax);
  };
  _findMax(value);
  return max;
};

console.log(findMax(data));

简单的将递归调用的返回值赋值给idKey

let newUserID = 0;
const newID = ( root, idKey ) => {
  if ( root.id > idKey ) {
    idKey = root.id;
  }
  root.children.forEach( ( obj ) => {
    idKey = newID( obj, idKey ); // <--------
  });
  return idKey;
}

newUserID = newID( data, newUserID );

console.log( newUserID );

如果没有这个赋值,无论你递归多少次,返回的值都将只取决于顶部if语句的结果。这解释了您收到的日志。

你可以这样做:

const data = {id: 1,name: 'John',parent_id: null,children: [{ id: 2, name: 'Tess', parent_id: 1, children: [] },{id: 3,name: 'Tom',parent_id: 1,children: [{id: 4,name: 'Harry',parent_id: 3,children: [{ id: 7, name: 'Thabo', parent_id: 4, children: [] }],},{ id: 5, name: 'Mary', parent_id: 3, children: [] },{ id: 6, name: 'Madge', parent_id: 3, children: [] },],},],}
const arr = [...JSON.stringify(data).matchAll(/"id":(\d+)/g)].map(([, n]) => +n)
const result = Math.max(...arr)

console.log(result)

首先,关于您的代码被破坏的原因:您只是错过了一项作业。你在哪里

   newID( obj, idKey );

您忽略了结果值。您需要将其分配回 idKey:

    idKey = newID( obj, idKey );

这将解决您的问题。我们还应注意,变量名称 newUserID 有点用词不当,因为它 不是 您将使用的新变量,而是找到的最高变量。也许 highestUserID 不会那么混乱?

但是,我们应该指出,这可以写得更简单,使用 Math .max 来完成繁重的工作和一些递归。我可能会这样写:

const maxId = ({id, children = []}) =>
  Math .max (id, ... children .map (maxId))

const data = {id: 1, name: "John", parent_id: null, children: [{id: 2, name: "Tess", parent_id: 1, children: []}, {id: 3, name: "Tom", parent_id: 1, children: [{id: 4, name: "Harry", parent_id: 3, children: [{id: 7, name: "Thabo", parent_id: 4, children: []}]}, {id: 5, name: "Mary", parent_id: 3, children: []}, {id: 6, name: "Madge", parent_id: 3, children: []}]}]}

console .log (maxId (data))