Search code examples
javascriptarraysrecursionhierarchical

Javascript Recursive Merge of Hierarchical Data Based on Key


I have a set of arrays:

sample = [
{
    'name' : 'alpha',
    'inner' : [
        {
            'name' : 'beta',
            'inner' : [
                {
                    'name' : 'gamma',
                    'inner' : [
                        {
                            'name' : 'one',
                            'inner' : []
                        }
                    ]
                }
            ]
        }
    ]
},
{
    'name' : 'alpha',
    'inner' : [
        {
            'name' : 'beta',
            'inner' : [
                {
                    'name' : 'gamma',
                    'inner' : [
                        {
                            'name' : 'two',
                            'inner' : []
                        }
                    ]
                }
            ]
        }
    ]
},
{
    'name' : 'epsilon',
    'inner' : [
        {
            'name' : 'one',
            'inner' : []
        }
    ]
},
{
    'name' : 'epsilon',
    'inner' : [
        {
            'name' : 'two',
            'inner' : []
        }
    ]
}
]

Which i would like to merge recursively into this:

sample = [
{
    'name' : 'alpha',
    'inner' : [
        {
            'name' : 'beta',
            'inner' : [
                {
                    'name' : 'gamma',
                    'inner' : [
                        {
                            'name' : 'one',
                            'inner' : []
                        },
                        {
                            'name' : 'two',
                            'inner' : []
                        }
                    ]
                }
            ]
        }
    ]
},
{
    'name' : 'epsilon',
    'inner' : [
        {
            'name' : 'one',
            'inner' : []
        },
        {
            'name' : 'two',
            'inner' : []
        }
    ]
}]

Here is what i have so far:

As i understand this is how it should work, meaning that having a recursive that goes into each "inner" and then merges the arrays.

function _merge(arr) {
//
var result = [];
//
for (var i = 0; i < arr.length; i++) {
    var found = false;
    //
    for (var j = 0; j < result.length; j++) {
        //
        if ( result[j].name == arr[i].name) {
            found = true;
            //
            result[j].inner = result[j].inner.concat(arr[i].inner);
            //
            break;
        }
    }
    if (!found) {
        //
        result.push(arr[i]);
        //
    }
}
//
return result
//
}

//
function traverse(o ) {
    for (i in o) {
        if (!!o[i] && typeof(o[i])=="object") {
            //
            try{
                //
                build_array[i] = _merge(o[i])
                //
            }catch(e){
                //
                build_array = o[i]
                //
            }
            //
            traverse(o[i].inner );
        }
    }
}   
//

Thank you for you help


Solution

  • This is what u want:

    function merge(sourceArray,lastResult){
    
                        var output=lastResult || [];
                        sourceArray.forEach(function(sourceItem){
    
                            var founded=output.filter(function(item){
                                return item.name==sourceItem.name;
                            })[0];
    
                            if(!founded){
                                founded={
                                    name:sourceItem.name,
                                    inner:[]
                                };
                                output.push(founded);
                            }
    
    
                            founded.inner= merge(sourceItem.inner||[],founded.inner)
                        });
                        return output;
                    }
    
    
                    var source = [
                        {
                            'name' : 'alpha',
                            'inner' : [
                                {
                                    'name' : 'beta',
                                    'inner' : [
                                        {
                                            'name' : 'gamma',
                                            'inner' : [
                                                {
                                                    'name' : 'one',
                                                    'inner' : []
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            'name' : 'alpha',
                            'inner' : [
                                {
                                    'name' : 'beta',
                                    'inner' : [
                                        {
                                            'name' : 'gamma',
                                            'inner' : [
                                                {
                                                    'name' : 'two',
                                                    'inner' : []
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            'name' : 'epsilon',
                            'inner' : [
                                {
                                    'name' : 'one',
                                    'inner' : []
                                }
                            ]
                        },
                        {
                            'name' : 'epsilon',
                            'inner' : [
                                {
                                    'name' : 'two',
                                    'inner' : []
                                }
                            ]
                        }
                    ];
    
                    console.log(merge(source));