Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flatten hierarchical data

I have a data structure like this:

{
    name: 'test',
    config: { ... },
    prev: {
        name: 'test1.1',
        config: { ... },
        prev: {
            name: 'test1.1.1',
            config: { ... },
            prev: {
                name: 'test1.1.1.1',
                config: { ... },
                prev: undefined
            }
        }
    }
}

The structure can contain any number of recursive but identical structures inside the 'prev' object.

I want to extract the 'name' property of each child. How can I flatten this using underscore to produce a resultset like so:

['test', 'test1.1', 'test1.1.1', 'test1.1.1.1']

It would be even greater if the flattening process could return something like

[
    {name: 'test', config: { ... }}, 
    {name: 'test1.1', config: { ... }}, 
    {name: 'test1.1.1', config: { ... }},
    {name: 'test1.1.1.1', config: { ... }}
]

My current solution is this (which is not optimal. I would like to use one _.chain to produce this):

var _self = {
    flatten: function (obj) {
        var map = [];
        return _self.flattenRecurse(obj, map);
    },
    flattenRecurse: function (obj, map) {
        map.push({name: obj.name, config: obj.config});
        if (obj.prev) {
            _self.flattenRecurse(obj.prev, map);
        }
    }
}
var flattened = _self.flatten(data);
like image 394
Øystein Amundsen Avatar asked Feb 11 '15 12:02

Øystein Amundsen


1 Answers

It's easier to use plain js, like this

const data = {
    name: 'test',
    config: { },
    prev: { name: 'test1.1',
        config: { },
        prev: {
            name: 'test1.1.1',
            config: {  },
            prev: { name: 'test1.1.1.1', config: { }, prev: undefined }
        }
    }
};

function flatten (data) {
  let result = [];
  
  while (data) {
    result.push({ name: data.name, config: data.config });
    data = data.prev;
  }
  
  return result;
}

console.log(flatten(data));

// get only names
const res = flatten(data).map(el => el.name);
console.log(res);
like image 129
Oleksandr T. Avatar answered Oct 05 '22 19:10

Oleksandr T.