【问题标题】:Javascript Recursive Merge of Hierarchical Data Based on Key基于键的分层数据的Javascript递归合并
【发布时间】:2017-07-31 15:31:35
【问题描述】:

我有一组数组:

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' : []
        }
    ]
}
]

我想递归合并到这个:

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' : []
        }
    ]
}]

这是我目前所拥有的:

据我了解,它应该是这样工作的,这意味着有一个递归进入每个“内部”,然后合并数组。

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 );
        }
    }
}   
//

感谢您的帮助

【问题讨论】:

  • 我会请求你分享这个递归函数。是的,它可能会把我们引向错误的方向,但我们仍然会知道从哪里开始寻找
  • 好的,我马上贴出来
  • 这个问题好像少了一个问题?

标签: javascript arrays recursion hierarchical


【解决方案1】:

这就是你想要的:

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));

【讨论】:

  • 欢迎您。但是如果您的数组具有较深的层次结构,那么您不应该使用递归方法,因为您会遇到“堆栈溢出”错误。那么你应该有自己的堆栈。
【解决方案2】:

您可以使用迭代和递归的方法来合并相同的命名对象。

var data = [{ 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: [] }] }],
    result = [];

data.forEach(function iter(r) {
    return function (a) {
        var o;
        if (!r.some(function (b) { if (a.name === b.name) { o = b; return true; } })) {
            r.push(a);
            return;
        }
        Array.isArray(a.inner) && a.inner.forEach(iter(o.inner = o.inner || []));
    };
}(result));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

对于您可以添加的其他属性

Object.keys(a).forEach(function (k) {
    if (['name', 'inner'].indexOf(k) === -1) {
        o[k] = a[k];
    }
});

用于迭代所有属性并仅分配不是nameinner 的键。

var data = [{ name: 'alpha', data1: '1', inner: [{ name: 'beta', data2: '2', inner: [{ name: 'gamma', data3: '3', inner: [{ name: 'one', data4: '4', inner: [] }] }] }] }, { name: 'alpha', data5: '5', inner: [{ name: 'beta', data6: '6', inner: [{ name: 'gamma', data7: '7', inner: [{ name: 'two', data8: '8', inner: [] }] }] }] }, { name: 'epsilon', data9: '9', inner: [{ name: 'one', data10: '10', inner: [] }] }, { name: 'epsilon', data11: '11', inner: [{ name: 'two', data12: '12', inner: [] }] }],
    result = [];

data.forEach(function iter(r) {
    return function (a) {
        var o;
        if (!r.some(function (b) { if (a.name === b.name) { o = b; return true; } })) {
            r.push(a);
            return;
        }
        Object.keys(a).forEach(function (k) {
            if (['name', 'inner'].indexOf(k) === -1) {
                o[k] = a[k];
            }
        });
        Array.isArray(a.inner) && a.inner.forEach(iter(o.inner = o.inner || []));
    };
}(result));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 你好,如果有额外的数据,那将如何修改? [ { 'name' : 'alpha', 'inner' : [], 'data':'one' } ]
  • 那么您需要迭代原始数据并将其添加到结果对象中。我可以在一个小时内写一个例子。
  • 如果可能的话,我希望看到您对 for 循环而不是 foreach 的看法。谢谢
  • 为什么要使用 for 循环?它有什么好处?
  • data 属性会发生什么?覆盖,收集?
猜你喜欢
  • 1970-01-01
  • 2018-05-03
  • 2020-07-12
  • 1970-01-01
  • 2018-08-21
  • 2015-06-08
  • 2010-09-08
  • 1970-01-01
  • 2018-10-11
相关资源
最近更新 更多