我有一个复杂的json文件,我必须处理javascript使其分层,以便稍后构建树。 json的每个条目都有: Id:唯一的Id, parentId:父节点的id(如果节点是树的根,则为0) Level:树的深度级别

json数据已经“有序”。我的意思是,一个条目在它上面有一个父节点或兄弟节点,在它下面有一个子节点或兄弟节点。

输入:

{
    "People": [
        {
            "id": "12",
            "parentId": "0",
            "text": "Man",
            "level": "1",
            "children": null
        },
        {
            "id": "6",
            "parentId": "12",
            "text": "Boy",
            "level": "2",
            "children": null
        },
                {
            "id": "7",
            "parentId": "12",
            "text": "Other",
            "level": "2",
            "children": null
        },
        {
            "id": "9",
            "parentId": "0",
            "text": "Woman",
            "level": "1",
            "children": null
        },
        {
            "id": "11",
            "parentId": "9",
            "text": "Girl",
            "level": "2",
            "children": null
        }
    ],
    "Animals": [
        {
            "id": "5",
            "parentId": "0",
            "text": "Dog",
            "level": "1",
            "children": null
        },
        {
            "id": "8",
            "parentId": "5",
            "text": "Puppy",
            "level": "2",
            "children": null
        },
        {
            "id": "10",
            "parentId": "13",
            "text": "Cat",
            "level": "1",
            "children": null
        },
        {
            "id": "14",
            "parentId": "13",
            "text": "Kitten",
            "level": "2",
            "children": null
        },
    ]
}

预期产量:

{
    "People": [
        {
            "id": "12",
            "parentId": "0",
            "text": "Man",
            "level": "1",
            "children": [
                {
                    "id": "6",
                    "parentId": "12",
                    "text": "Boy",
                    "level": "2",
                    "children": null
                },
                {
                    "id": "7",
                    "parentId": "12",
                    "text": "Other",
                    "level": "2",
                    "children": null
                }   
            ]
        },
        {
            "id": "9",
            "parentId": "0",
            "text": "Woman",
            "level": "1",
            "children":
            {

                "id": "11",
                "parentId": "9",
                "text": "Girl",
                "level": "2",
                "children": null
            }
        }

    ],    

    "Animals": [
        {
            "id": "5",
            "parentId": "0",
            "text": "Dog",
            "level": "1",
            "children": 
                {
                    "id": "8",
                    "parentId": "5",
                    "text": "Puppy",
                    "level": "2",
                    "children": null
                }
        },
        {
            "id": "10",
            "parentId": "13",
            "text": "Cat",
            "level": "1",
            "children": 
            {
                "id": "14",
                "parentId": "13",
                "text": "Kitten",
                "level": "2",
                "children": null
            }
        }

    ]
}

当前回答

没有第三方库 不需要预先排序数组 你可以得到树的任何部分

试试这个

function getUnflatten(arr,parentid){
  let output = []
  for(const obj of arr){
    if(obj.parentid == parentid)

      let children = getUnflatten(arr,obj.id)

      if(children.length){
        obj.children = children
      }
      output.push(obj)
    }
  }

  return output
 }

在Jsfiddle上测试它

其他回答

正如@Sander提到的,@Halcyon的答案假设一个预先排序的数组,下面的不是。(然而,它假设你已经加载了underscore.js -尽管它可以用香草javascript编写):

Code

// Example usage var arr = [ {'id':1 ,'parentid' : 0}, {'id':2 ,'parentid' : 1}, {'id':3 ,'parentid' : 1}, {'id':4 ,'parentid' : 2}, {'id':5 ,'parentid' : 0}, {'id':6 ,'parentid' : 0}, {'id':7 ,'parentid' : 4} ]; unflatten = function( array, parent, tree ){ tree = typeof tree !== 'undefined' ? tree : []; parent = typeof parent !== 'undefined' ? parent : { id: 0 }; var children = _.filter( array, function(child){ return child.parentid == parent.id; }); if( !_.isEmpty( children ) ){ if( parent.id == 0 ){ tree = children; }else{ parent['children'] = children } _.each( children, function( child ){ unflatten( array, child ) } ); } return tree; } tree = unflatten( arr ); document.body.innerHTML = "<pre>" + (JSON.stringify(tree, null, " ")) <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

需求

它假设属性'id'和'parentid'分别表示id和父id。必须有父ID为0的元素,否则将返回一个空数组。孤儿元素及其后代“丢失”

http://jsfiddle.net/LkkwH/1/

下面是我根据上面的答案创建的一个简单的帮助函数,为通天塔环境量身定制:

import { isEmpty } from 'lodash'

export default function unflattenEntities(entities, parent = {id: null}, tree = []) {

  let children = entities.filter( entity => entity.parent_id == parent.id)

  if (!isEmpty( children )) {
    if ( parent.id == null ) {
      tree = children
    } else {
      parent['children'] = children
    }
    children.map( child => unflattenEntities( entities, child ) )
  }

  return tree

}

我有类似的问题,几天前必须从平面数组显示文件夹树。我在TypeScript中没有看到任何解决方案,所以我希望它会有帮助。

在我的情况下,主父只有一个,rawData数组也不需要排序。解决方案基于准备临时对象 {parentId: [child1, child2,…]]}

示例原始数据

const flatData: any[] = Folder.ofCollection([
  {id: '1', title: 'some title' },
  {id: '2', title: 'some title', parentId: 1 },
  {id: '3', title: 'some title', parentId: 7 },
  {id: '4', title: 'some title', parentId: 1 },
  {id: '5', title: 'some title', parentId: 2 },
  {id: '6', title: 'some title', parentId: 5 },
  {id: '7', title: 'some title', parentId: 5 },

]);

文件夹的定义

export default class Folder {
    public static of(data: any): Folder {
        return new Folder(data);
    }

    public static ofCollection(objects: any[] = []): Folder[] {
        return objects.map((obj) => new Folder(obj));
    }

    public id: string;
    public parentId: string | null;
    public title: string;
    public children: Folder[];

    constructor(data: any = {}) {
        this.id = data.id;
        this.parentId = data.parentId || null;
        this.title = data.title;
        this.children = data.children || [];
    }
}

解决方案:返回扁平参数的树结构的函数

    public getTree(flatData: any[]): Folder[] {
        const addChildren = (item: Folder) => {
            item.children = tempChild[item.id] || [];
            if (item.children.length) {
                item.children.forEach((child: Folder) => {
                    addChildren(child);
                });
            }
        };

        const tempChild: any = {};
        flatData.forEach((item: Folder) => {
            const parentId = item.parentId || 0;
            Array.isArray(tempChild[parentId]) ? tempChild[parentId].push(item) : (tempChild[parentId] = [item]);
        });

        const tree: Folder[] = tempChild[0];
        tree.forEach((base: Folder) => {
            addChildren(base);
        });
        return tree;
    }

ES6地图版本:

getTreeData = (items) => {
  if (items && items.length > 0) {
    const data = [];
    const map = {};
    items.map((item) => {
      const id = item.id; // custom id selector !!!
      if (!map.hasOwnProperty(id)) {
        // in case of duplicates
        map[id] = {
          ...item,
          children: [],
        };
      }
    });
    for (const id in map) {
      if (map.hasOwnProperty(id)) {
        let mappedElem = [];
        mappedElem = map[id];
        /// parentId : use custom id selector for parent
        if (
          mappedElem.parentId &&
          typeof map[mappedElem.parentId] !== "undefined"
        ) {
          map[mappedElem.parentId].children.push(mappedElem);
        } else {
          data.push(mappedElem);
        }
      }
    }
    return data;
  }
  return [];
};

/// use like this :

const treeData = getTreeData(flatList);

你可以使用npm包数组到树https://github.com/alferov/array-to-tree。 它将普通的节点数组(带有指向父节点的指针)转换为嵌套的数据结构。

解决了从数据库数据集检索到嵌套数据结构(即导航树)的转换问题。

用法:

var arrayToTree = require('array-to-tree');

var dataOne = [
  {
    id: 1,
    name: 'Portfolio',
    parent_id: undefined
  },
  {
    id: 2,
    name: 'Web Development',
    parent_id: 1
  },
  {
    id: 3,
    name: 'Recent Works',
    parent_id: 2
  },
  {
    id: 4,
    name: 'About Me',
    parent_id: undefined
  }
];

arrayToTree(dataOne);

/*
 * Output:
 *
 * Portfolio
 *   Web Development
 *     Recent Works
 * About Me
 */