Underscore to flatten nested array of parent/child

2019-01-23 16:10发布

问题:

I have an array of objects, where each object has a "children" property (example data below). I want to flatten parents/children into a single array, with each parent immediately followed by it's children.

I've written the following using lo-dash / underscore, and it works when I have one and only one child for each parent:

_.flatten(_.zip(myArr, _.flatten(myArr, "children")))

I know I can use something like _.each and build an object, just wondering if there's a snazzy way to do this using _.

Example Data:

[{
    name: "Some Name",
    value: 1234,
    children: [{
        name: "Another name",
        value: 3456
    }, {
        name: "A third name",
        value: 9876
    }]
}, {
    name: "Omg Lazer Guns",
    value: 3333,
    children: [{
        name: "PewPewPew",
        value: 4444
    }]
}];

回答1:

A simple and more readable way to do this is

var list = [];
_.each(data, function(item){
    list.push(_.omit(item, 'children'));
    list.push(_.flatten(_.pick(item, 'children')));
});
var result = _.flatten(list);

The result is

[{
    "name": "Some Name",
    "value": 1234
}, {
    "name": "Another name",
    "value": 3456
}, {
    "name": "A third name",
    "value": 9876
}, {
    "name": "Omg Lazer Guns",
    "value": 3333
}, {
    "name": "PewPewPew",
    "value": 4444
}]


回答2:

The usual approach to merge arrays they way you want to is to zip them and You can use pluck to extract the children. Something like this:

var mangled = _(myArr).chain()
                      .zip(_(myArr).pluck('children'))
                      .flatten() 
                      .value()

That will leave you with undefined entries in mangled if any of the top-level elements of myArr don't have children keys at all. You can throw in a compact to get rid of those:

var mangled = _(myArr).chain()
                      .zip(_(myArr).pluck('children'))
                      .flatten()
                      .compact()
                      .value()

Demo: http://jsfiddle.net/ambiguous/aeS86/

Of course, doing the mangling with a a couple for loops and some push calls will probably be faster but the speed difference shouldn't matter with short arrays.