{"id":13602627,"url":"https://github.com/yi-ge/js-tree-list","last_synced_at":"2025-08-09T01:37:56.450Z","repository":{"id":57283776,"uuid":"118592337","full_name":"yi-ge/js-tree-list","owner":"yi-ge","description":"Convert list to tree, managing a tree and its nodes.","archived":false,"fork":false,"pushed_at":"2018-09-18T03:14:39.000Z","size":91,"stargazers_count":30,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"dev","last_synced_at":"2025-04-13T01:12:26.712Z","etag":null,"topics":["algorithm","tree","tree-to-list"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yi-ge.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-01-23T10:05:24.000Z","updated_at":"2025-02-06T16:03:06.000Z","dependencies_parsed_at":"2022-09-19T22:41:35.443Z","dependency_job_id":null,"html_url":"https://github.com/yi-ge/js-tree-list","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yi-ge%2Fjs-tree-list","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yi-ge%2Fjs-tree-list/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yi-ge%2Fjs-tree-list/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yi-ge%2Fjs-tree-list/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yi-ge","download_url":"https://codeload.github.com/yi-ge/js-tree-list/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248650754,"owners_count":21139681,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithm","tree","tree-to-list"],"created_at":"2024-08-01T18:01:32.134Z","updated_at":"2025-04-13T01:12:39.573Z","avatar_url":"https://github.com/yi-ge.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# js-tree-list\n\n[![npm version](https://img.shields.io/npm/v/js-tree-list.svg?style=flat-square)](https://www.npmjs.org/package/js-tree-list)\n[![build status](https://img.shields.io/travis/yi-ge/js-tree-list.svg?style=flat-square)](https://travis-ci.org/yi-ge/js-tree-list)\n[![Codecov](https://img.shields.io/codecov/c/github/yi-ge/js-tree-list.svg?style=flat-square)](https://codecov.io/gh/yi-ge/js-tree-list)\n[![code coverage](https://img.shields.io/coveralls/yi-ge/js-tree-list.svg?style=flat-square)](https://coveralls.io/github/yi-ge/js-tree-list)\n[![npm](https://img.shields.io/npm/dt/js-tree-list.svg?style=flat-square)](http://npm-stat.com/charts.html?package=js-tree-list)\n[![license](https://img.shields.io/github/license/yi-ge/js-tree-list.svg?style=flat-square)](https://github.com/yi-ge/js-tree-list/blob/master/LICENSE)\n[![GitHub last commit](https://img.shields.io/github/last-commit/yi-ge/js-tree-list.svg?style=flat-square)](https://github.com/yi-ge/js-tree-list)\n[![bitHound](https://img.shields.io/bithound/dependencies/github/yi-ge/js-tree-list.svg?style=flat-square)](https://www.bithound.io/github/yi-ge/js-tree-list)\n\n[![GitHub release](https://img.shields.io/github/release/yi-ge/js-tree-list.svg?style=flat-square)](https://github.com/yi-ge/js-tree-list/releases)\n[![Github file size](https://img.shields.io/github/size/yi-ge/js-tree-list/bin/js-tree-list.min.js.svg?style=flat-square)](https://github.com/yi-ge/js-tree-list/blob/master/bin/js-tree-list.min.js)\n[![codebeat badge](https://codebeat.co/badges/1e0be277-b609-4336-a4aa-b18c2cb94951)](https://codebeat.co/projects/github-com-yi-ge-js-tree-list-master)\n[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fyi-ge%2Fjs-tree-list.svg?type=small)](https://app.fossa.io/projects/git%2Bgithub.com%2Fyi-ge%2Fjs-tree-list?ref=badge_small)\n\n[![JavaScript Style Guide](https://cdn.rawgit.com/standard/standard/master/badge.svg)](https://github.com/standard/standard)\n\nConvert list to tree, managing a tree and its nodes.\n\nFork from:\nhttps://github.com/DenQ/iron-tree\nhttps://github.com/DenQ/list-to-tree\n\nThe author of this project is [DenQ](https://github.com/DenQ). This project has only been improved a little.\n\n**There is a known bug that may be reported incorrectly when the list order is incorrect. The temporary alternative is as follows:**\n\n```js\n// 获取描述对象的值\nexport const getObjectValue = (obj, des) =\u003e {\n  return eval('obj.' + des) // eslint-disable-line\n}\n\n/**\n * 将json按一定规律组合成父子模式\n * @param  {[type]} data                        json数据\n * @param  {Number} [minPid=0]                  最大的父ID（可能不是0，最大的是几就填几，就从几开始排）\n * @param  {String} [IDString='ID']             ID的别名\n * @param  {String} [pidString='pid']           父ID的别名\n * @param  {String} [childrenString='children'] 生成的子的别名（子的数据就在这个名称下）\n * @return {[type]}                             父子JSON\n */\nexport const toTreeData = (\n  data,\n  minPid = 0,\n  IDString = 'ID',\n  pidString = 'pid',\n  childrenString = 'children',\n  sort = 'sort'\n) =\u003e {\n  let pos = {}\n  let tree = []\n  let n = 0\n\n  if (minPid === 'null') {\n    minPid = null\n  }\n\n  while (data.length !== 0) {\n    if (getObjectValue(data[n], pidString) == minPid) { // eslint-disable-line\n      // delete getObjectValue(data[n], pidString)\n      data[n][childrenString] = []\n      tree.push(data[n])\n      pos[getObjectValue(data[n], IDString)] = [tree.length - 1]\n      data.splice(n, 1)\n      n--\n    } else {\n      let posArray = pos[getObjectValue(data[n], pidString)]\n      if (posArray !== undefined) {\n        let obj = tree[posArray[0]]\n        for (let j = 1; j \u003c posArray.length; j++) {\n          obj = obj[childrenString][posArray[j]]\n        }\n        // delete getObjectValue(data[n], pidString)\n        data[n][childrenString] = []\n        obj[childrenString].push(data[n])\n        pos[getObjectValue(data[n], IDString)] = posArray.concat([\n          obj[childrenString].length - 1\n        ])\n        data.splice(n, 1)\n        n--\n      }\n    }\n    n++\n    if (n \u003e data.length - 1) {\n      n = 0\n    }\n  }\n\n  // sort\n  const toSort = (tree) =\u003e {\n    tree.sort((a, b) =\u003e {\n      return a[sort] - b[sort]\n    })\n  }\n\n  const ergodicTree = (tree) =\u003e {\n    for (const n in tree) {\n      if (tree[n][childrenString] \u0026\u0026 tree[n][childrenString].length) {\n        toSort(tree[n][childrenString])\n        ergodicTree(tree[n][childrenString])\n      }\n    }\n  }\n\n  toSort(tree)\n  ergodicTree(tree)\n\n  return tree\n}\n```\n\n**You can use it**\n```js\nconsole.time('tree算法')\nconst girdData = toTreeData(tmp, 'null', 'dataUuid', 'parentUuid', '_children')\nconsole.timeEnd('tree算法')\n```\n\n## Features\n\n* Convert list to tree.\n* Convert tree to list.\n* Tree sort by `last`.\n* UUID is support.\n\n## Installation\n\n```\n$ npm install js-tree-list\n```\n\n## Usage\n\n```js\n// JsTreeList.ListToTree Config\nconst defaultOptions = {\n  key_id: 'id',\n  key_parent: 'parent',\n  key_child: 'child',\n  key_last: null,\n  uuid: false,\n  empty_children: false\n}\n```\n\n```js\nimport JsTreeList from \"js-tree-list\"\nvar list = [\n  {\n    id: 1,\n    parent: 0\n  },\n  {\n    id: 2,\n    parent: 1\n  },\n  {\n    id: 3,\n    parent: 1\n  },\n  {\n    id: 4,\n    parent: 2\n  },\n  {\n    id: 5,\n    parent: 2\n  },\n  {\n    id: 6,\n    parent: 0\n  },\n  {\n    id: 7,\n    parent: 0\n  },\n  {\n    id: 8,\n    parent: 7\n  },\n  {\n    id: 9,\n    parent: 8\n  },\n  {\n    id: 10,\n    parent: 0\n  }\n]\n\nconst tree = new JsTreeList.ListToTree(list, {\n  key_id: \"id\",\n  key_parent: \"parent\",\n  key_child: \"children\",\n  key_last: \"last\"\n}).GetTree()\n\nconst list = new JsTreeList.TreeToList(tree, {\n  key_child: \"children\",\n  empty_children: true\n}).GetList()\n\nconsole.log(tree)\nconsole.log(list)\n```\n\n###### Result\n\n    [{\n        \"id\": 1,\n        \"parent\": 0,\n        \"child\": [\n            {\n                \"id\": 2,\n                \"parent\": 1,\n                \"child\": [\n                    {\n                        \"id\": 4,\n                        \"parent\": 2\n                    }, {\n                        \"id\": 5,\n                        \"parent\": 2\n                    }\n                ]\n            },\n            {\n                \"id\": 3,\n                \"parent\": 1\n            }\n        ]\n    }, {\n        \"id\": 6,\n        \"parent\": 0\n    }, {\n        \"id\": 7,\n        \"parent\": 0,\n        \"child\": [\n            {\n                \"id\": 8,\n                \"parent\": 7,\n                \"child\": [\n                    {\n                        \"id\": 9,\n                        \"parent\": 8\n                    }\n                ]\n            }\n        ]\n    }, {\n        \"id\": 10,\n        \"parent\": 0\n    }];\n\n# Methods\n\n* **constructor(list, options)**\n  * params:\n    * `list` - array list with elements. Like `{ id: 5: parent: 1 }`.\n    * `options` - optional parameter. Object for describe flags and field names for tree.\n* **.GetTree()** This method will be return json tree\n  * example:\n    ```\n      tree.GetTree()\n    ```\n* **.sort(callback)** The custom sort method\n  * callback(a, b) - a and b have `Node` type and have methods: add, remove, get, set, sort, traversal, etc...\n  * example:\n    ```js\n    function compareById(vector) {\n      return (a, b) =\u003e {\n        const aid = Number(a.get(\"id\"))\n        const bid = Number(b.get(\"id\"))\n        if (aid \u003e bid) {\n          return vector ? 1 : -1\n        } else if (aid \u003c bid) {\n          return vector ? -1 : 1\n        } else {\n          return 0\n        }\n      }\n    }\n    ltt.sort(compareById(false))\n    ```\n\n# The Tree and Node Base usage\n\n```js\n// create tree\nimport JsTreeList from \"js-tree-list\"\nconst object = { id: 1, title: \"Root\" }\nconst tree = new JsTreeList.Tree(object)\n\n// add nodes\nconst regularObject = { id: 2, title: \"Node 2\" }\ntree.add(parentNode =\u003e {\n  return parentNode.get(\"id\") === 1\n}, regularObject)\n\n// contains node\nconst targetNode = tree.contains(currentNode =\u003e {\n  return currentNode.get(\"id\") === 2\n})\n\n// remove node\nconst result = tree.remove(currentNode =\u003e {\n  return currentNode.get(\"id\") === 2\n})\n\n// traversal\nconst criteria = currentNode =\u003e currentNode.get(\"id\") === 1\ntree.traversal(criteria, currentNode =\u003e {\n  currentNode.set(\"some\", true)\n})\n```\n\n```js\nfunction compareById(vector) {\n  return (a, b) =\u003e {\n    const aid = Number(a.get(\"id\"))\n    const bid = Number(b.get(\"id\"))\n    if (aid \u003e bid) {\n      return vector ? 1 : -1\n    } else if (aid \u003c bid) {\n      return vector ? -1 : 1\n    } else {\n      return 0\n    }\n  }\n}\ntree.sort(compareById(false)) // desc\n```\n\nThe following are the other methods available.\n\n---\n\n# Tree\n\nThis is the class of tree management\n\n### Properties\n\n* **rootNode** Root tree node\n  * type `Node`\n\n### Methods\n\n* **contstructor(object)**\n  * params\n    * object - json `object`. Optional\n  * return `Three`\n  * example\n  ```js\n  const object = { id: 1, title: \"Root\" }\n  const tree = new JsTreeList.Tree(object)\n  ```\n* **.add(criteria, object)** Adds a node to the tree if the criterion is true\n  * params\n    * criteria(Node) - `function` or `string`. If `string` then criteria is **\"root\"**\n    * object - content for the node\n  * return `Three`\n  * examples\n  ```js\n  const object = { id: 1, title: \"Root\" }\n  const tree = new JsTreeList.Tree()\n  const resultTree = tree.add(\"root\", object)\n  ```\n  ```js\n  const regularObject = { id: 2, title: \"Node 2\" }\n  const resultTree = tree.add(parentNode =\u003e {\n    return parentNode.get(\"id\") === 1\n  }, regularObject)\n  ```\n* **.remove(criteria)** Removes a node from a tree if the criterion is true\n  * params\n    * criteria(Node) - return `boolean`\n  * return `boolean`\n  * examples\n  ```js\n  const result = tree.remove(currentNode =\u003e {\n    return currentNode.get(\"id\") === 7\n  })\n  ```\n* **.contains(criteria)** Searches for a node in a tree according to the criterion\n\n  * params\n    * criteria(Node) - return `boolean`\n  * return `Node`\n  * examples\n\n  ```js\n  const targetNode = tree.contains(currentNode =\u003e {\n    return currentNode.get(\"id\") === 7\n  })\n  ```\n\n* **.sort(compare)** Sorts a tree\n  * params\n    * compare(a:Node, b:Node) - comparison function\n  * return `null`\n  * examples\n  ```js\n  function compareById(vector) {\n    return (a, b) =\u003e {\n      const aid = Number(a.get(\"id\"))\n      const bid = Number(b.get(\"id\"))\n      if (aid \u003e bid) {\n        return vector ? 1 : -1\n      } else if (aid \u003c bid) {\n        return vector ? -1 : 1\n      } else {\n        return 0\n      }\n    }\n  }\n  tree.sort(compareById(false)) //Desc\n  ```\n* **.move(criteria, destination)** Moves the desired branch or node to the node or branch of the destination, according to the criteria\n  * params\n    * criteria(Node) - callback\n    * destination(Node) - callback\n  * return `boolean`\n  * examples\n  ```js\n  const search = currentNode =\u003e currentNode.get(\"id\") === 7\n  const destination = currentNode =\u003e currentNode.get(\"id\") === 3\n  const result = tree.move(search, destination)\n  ```\n* **.traversal(criteria, callback)** Bypasses the tree and, according to the criterion, calls a function for each node\n  * params\n    * criteria(Node) - return `boolean`\n    * callback(Node)\n  * return `null`\n  * examples\n  ```js\n  const criteria = currentNode =\u003e currentNode.get(\"id\") === 7\n  tree.traversal(criteria, currentNode =\u003e {\n    currentNode.set(\"some\", true)\n  })\n  ```\n  ```js\n  tree.traversal(null, currentNode =\u003e {\n    if (currentNode.get(\"id\") % 2 === 0) {\n      currentNode.set(\"some\", true)\n    }\n  })\n  ```\n* **.toJson(options)** Represents a tree in the form of a json format\n  * params\n    * options - `object`. Optional\n      * empty_children - Type `boolean`. Allow empty children. Default `true`\n      * key_children - Type `string`. Field name for children. Default `children`\n  * return `object`\n  * examples\n  ```js\n  const json = tree.toJson()\n  ```\n\n---\n\n# Node\n\nThis is the node management class\n\n### Properties\n\n* **content** Content of the node\n  * type `object`\n* **children** Children of the node\n  * type `array`\n* **length** Number children of the node\n  * type `number`\n\n### Methods\n\n* **constructor(json)**\n\n  * params\n    * json - simple `json` object\n  * examples\n\n  ```js\n  import JsTreeList from \"js-tree-list\"\n  const rootContent = {\n    id: 1,\n    name: \"Root\"\n  }\n  let node = new JsTreeList.Node(rootContent)\n  ```\n\n* **.add(child)** Adding a child to the node\n  * return `Node` - created node\n  * params\n    * child - type `object`/json\n  * examples\n  ```js\n  const rootContent = {\n    id: 1,\n    name: \"Root\"\n  }\n  let node = new JsTreeList.Node(rootContent)\n  const childNode = node.add({ id: 2, name: \"Two node\" })\n  ```\n* **.remove(criteria)** Removing a child node according to the criterion\n\n  * return - removed `Node`\n  * params\n    * criteria - criteria function for removing nodes\n  * examples\n\n  ```js\n  const removedNodes = node.remove(itemNode =\u003e {\n    return itemNode.get(\"id\") === 3\n  })\n  ```\n\n* **.get(path)** Access to node content by field name\n  * return `mixed`\n  * params\n    * path - key name for object in node. For example `id` or `fullname`, etc...\n  * examples\n  ```js\n  node.get(\"id\") // 1\n  node.get(\"name\") // \"Some name\"\n  ```\n* **.set(path, value)** Setting a value or creating a new field in the contents of a node\n  * return `boolean`\n  * params\n    * path - `String` field name\n    * value - `mixed`\n  * examples\n  ```js\n  node.set('id', 100)); // returned `true`. Node.content.id = 100\n  node.get('id'); // 100\n  ```\n* **.sort(compare)** Sorting child nodes\n  * return `null`\n  * params\n    * compare - custom function for sorting\n  * examples\n  ```js\n  function compareById(vector) {\n    return (a, b) =\u003e {\n      const aid = Number(a.get(\"id\"))\n      const bid = Number(b.get(\"id\"))\n      if (aid \u003e bid) {\n        return vector ? 1 : -1\n      } else if (aid \u003c bid) {\n        return vector ? -1 : 1\n      } else {\n        return 0\n      }\n    }\n  }\n  node.sort(compareById(false))\n  ```\n* **.traversal(criteria, callback)** Bypassing child nodes according to the criterion and applying function to them\n  * return `null`\n  * params\n    * criteria - `function` criteria each nodes\n    * callback - `function` fire when criteria is true for node\n  * examples\n  ```js\n  // for all nodes\n  node.traversal(null, currentNode =\u003e {\n    const name = currentNode.get(\"name\")\n    currentNode.set(\"name\", `${name}!`) // Last symbol \"!\"\n  })\n  ```\n  ```js\n  // only for node.id == 3\n  node.traversal(\n    currentNode =\u003e currentNode.get(\"id\") === 3,\n    currentNode =\u003e {\n      const name = currentNode.get(\"name\")\n      currentNode.set(\"name\", `${name}!`) // Last symbol \"!\"\n    }\n  )\n  ```\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyi-ge%2Fjs-tree-list","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyi-ge%2Fjs-tree-list","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyi-ge%2Fjs-tree-list/lists"}