简体   繁体   English

Javascript递归树构建

[英]Javascript Recursion Tree Building

I am having an issue building a tree from a flat array.我在从平面数组构建树时遇到问题。 I am building a category -> subcategory tree in which the parent has subcategories as an array.我正在构建一个类别-> 子类别树,其中父级将子类别作为数组。

Here is what the flat array would look like:这是平面数组的样子:

[
  {
    "id": 1
  },
  {
    "id": 5,
  },
  {
    "id": 2,
    "parent_id": 1
  },
  {
    "id": 3,
    "parent_id": 1
  },
  {
    "id": 42,
    "parent_id": 5
  },
  {
    "id": 67,
    "parent_id": 5
  }
]

And this is what I need the result to look:这就是我需要查看的结果:

[
  {
    "id":1,
    "subcategories":[
      {
        "id":2,
        "parent_id":1
      },
      {
        "id":3,
        "parent_id":1
      }
    ]
  },
  {
    "id":5,
    "subcategories":[
      {
        "id":42,
        "parent_id":5
      },
      {
        "id":67,
        "parent_id":5
      }
    ]
  }
]

I have tried to do this recursively by recursively searching for children and attaching it as an array and continuing to do so until I hit the bottom of the barrel but I am getting a cyclic structure.我试图通过递归搜索孩子并将其作为数组附加并继续这样做,直到我到达桶底,但我得到了一个循环结构。 It appears that the parent_id in traverse is always the id of the parent... any ideas:看来 traverse 中的 parent_id 始终是父级的 id ...任何想法:

tree(passingInFlatObjectHere);

function topLevel (data) {
  let blob = [];
  data.forEach((each) => {
    if (!each.parent_id) {
      blob.push(each);
    }
  });
  return blob;
}

function tree (data) {
  let blob = topLevel(data).map(function (each) {
    each.subcategories = traverse(data, each.id);
    return each;
  });
  return blob;
}

function traverse (data, parent_id) {
  let blob = [];
  if (!parent_id) {
    return blob;
  }
  data.forEach((each) => {
    if (each.id === parent_id) {
      each.subcategories = traverse(data, each.id);
      blob.push(each);
    }
  });
  return blob;
}

I don't just want to help you fix your problem but would also like to help you take full advantage of ES6我不仅想帮你解决问题,还想帮助你充分利用 ES6

First of all your topLevel function can be rewritten to this:首先,您的topLevel函数可以重写为:

function topLevel(data) {
  return data.filter(node => !node.parent_id);
}

Neat isn't it?整齐是不是? I also would recommend slightly changing tree for consistency but that's of course just stylistic.我还建议稍微改变tree以保持一致性,但这当然只是风格。

function tree(data) {
  return topLevel(data).map(each => {
    each.subcategories = traverse(data, each.id);
    return each;
  });
}

No logic issues so far.目前没有逻辑问题。 traverse , however, contains one, when you check each.id === parent_id .但是,当您检查each.id === parent_id时, traverse包含一个。 Like this, the functions searches for the node whose id is parent_id .像这样,函数搜索 id 为parent_id的节点。 Obviously a mistake.显然是一个错误。 You wanted each.parent_id === parent_id .你想要each.parent_id === parent_id

Your issue is solved now.你的问题现在已经解决了。 Stop reading if I bother you.如果我打扰你,请停止阅读。 But you could also take advantage of filter here and remove that slightly superfluous early exit and rewrite your function to:但是您也可以利用此处的filter并删除稍微多余的提前退出并将您的函数重写为:

function traverse(data, parentId) {
  const children = data.filter(each => each.parent_id === parentId);
  children.forEach(child => {
    child.subcategories = traverse(data, child.id);
  });
  return children;
}

First, you need install lodash with below command with npm:首先,您需要使用 npm 使用以下命令安装lodash

npm i lodash

Second, you must import _ from lodash其次,必须从 lodash 导入 _

import _ from "lodash";

Finally, run this function:最后,运行这个函数:

export const recursive_lists = (data) => {
  const grouped = _.groupBy(data, (item) => item. parent_id);

  function childrenOf(parent_id) {
    return (grouped[parent_id] || []).map((item) => ({
      id: item.id,
      child: childrenOf(item.id),
    }));
  }

  return childrenOf(null);
};

or或者

First:第一的:

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.20/lodash.min.js"></script>

Second:第二:

function recursive_lists(data) {
  const grouped = _.groupBy(data, (item) => item.parent_id);

  function childrenOf(parent_id) {
    return (grouped[parent_id] || []).map((item) => ({
      id: item.id,
      child: childrenOf(item.id),
    }));
  }

  return childrenOf(null);
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM