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.