如何使用Underscore.js从平面列表创建嵌套对象?

时间:2014-11-11 09:25:08

标签: javascript recursion nested underscore.js grouping

提供inputorder

input = [
    {
        "top": "peach", 
        "middle": "monkey",
        "bottom": "blue"
    },
    {
        "top": "peach", 
        "middle": "monkey",
        "bottom": "red"
    },
    {
        "top": "peach", 
        "middle": "cat",
        "bottom": "brown"
    },
    {
        "top": "peach", 
        "middle": "cat",
        "bottom": "black"
    },
    {
        "top": "peach", 
        "middle": "dog",
        "bottom": "purple"
    }
];

order = ["top", "middle", "bottom"];

生成“嵌套”output

output =     {
    "name": "peach",
    "children": [
        {
            "name": "monkey",
            "children": [
                { "name": "blue" },
                { "name": "red" }
            ]
        },
        {
            "name": "cat",
            "children": [
                { "name": "brown" },
                { "name": "black" }
            ]
        },
        {
            "name": "dog",
            "children": [
                { "name": "purple" }
            ]
        }
    ]
};

我知道这与_.groupBy()和使用递归有关,但我无法绕过它......

1 个答案:

答案 0 :(得分:2)

这是一个递归解决方案,在订单列表中的每个项目上使用 groupBy

var nestedGroup = function(list, order) {

    if( _.isEmpty(order)) return [];

    var groups = _.groupBy(list, _.first(order));

    return _.map(groups, function(children, key){
        var group = {
            name: key,
            children: nestedGroup(children, _.rest(order))
        };

        return _.isEmpty(group.children) ? _.omit(group, 'children') : group;
    });
}

var groups = nestedGroup(input, order);

angular.module('MyModule', [])

.controller('MyController', function( $scope ) {
  
	var input = [
	    {
	        "top": "peach", 
	        "middle": "monkey",
	        "bottom": "blue"
	    },
	    {
	        "top": "peach", 
	        "middle": "monkey",
	        "bottom": "red"
	    },
	    {
	        "top": "peach", 
	        "middle": "cat",
	        "bottom": "brown"
	    },
	    {
	        "top": "peach", 
	        "middle": "cat",
	        "bottom": "black"
	    },
	    {
	        "top": "peach", 
	        "middle": "dog",
	        "bottom": "purple"
	    }
	];

	var order = ["top", "middle", "bottom"];

	var nestedGroup = function(list, order) {

		if( _.isEmpty(order)) return [];

		var groups = _.groupBy(list, _.first(order));

		return _.map(groups, function(children, key){
			var group = {
				name: key,
				children: nestedGroup(children, _.rest(order))
			};

			return _.isEmpty(group.children) ? _.omit(group, 'children') : group;
		});
	}

	var groups = nestedGroup(input, order);
  
    $scope.groups = groups;
});

  
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>

<div ng-app='MyModule' ng-controller='MyController'>
  <p>{{groups || json}}</p>
</div>