简体   繁体   中英

With Underscore, how do I recursively flatten an array of objects?

I have a tree/traversable object that looks like this:

                var data = {children: [
                {
                name: 'foo',
                url: 'http://foo',
                children: [
                    {
                    name: 'bar',
                    url: 'http://bar',
                    children: []
                }
                ]
            },
            {
                name: 'baz',
                url: 'http://baz',
                children: []
            },
            {
                name: 'biff',
                children: []
            }
            ]};

What I need to do is be able to flatten the data into a single dimensional list:

var flattenedData = [{name: 'foo', url: 'http://foo'}, {name: 'bar', url: 'http://bar'}, {name: 'baz', url: 'http://baz'}, {name: 'biff'}];

Currently, I've created a recursive helper function to walk the data structure and push the results onto an array. I'd like to do this more functionally if possible. Something like:

var flattenedData = _.chain(data.children).flatten().filter(function(item){//real filtering; return item;}).value();

The problem is, flattening doesn't seem to flatten an array of objects, just simple arrays. I could be wrong.

How would I perform this task in a more functional way without traversing the tree in a helper function?

I don't see what you mean by "flatten doesn't seem to flatten an array of objects, just simple arrays" - how so? It most definitely can flatten any kind of array. Anyway, a simple one-pass solution using reduce :

Object.prototype.flatten = function () {
    if (this instanceof Array) {
        return this.reduce(function(a, b) {
            return a.concat(b.flatten());
        }, []);
    }

    var res = [];

    // this is the example condition
    if (this.url !== undefined) {
        res.push(this);
    }

    return res.concat(this.children.flatten());
};

var flat_data = data.flatten();
print(flat_data);

By the way, it would be advisable to replace Object with your custom data type you want to flatten, so that you don't mess up the global prototype for all objects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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