简体   繁体   中英

Merge an array of Javascript objects based on a Key Property (multilevel)

I have an array of Javascript objects that look like these:

data = [{PK: "Country1", Prop1: "true", children:[
                {PK: "State1", Prop1: "true", children:[
                        {PK: "City1", Prop1: "Value1"}]
                }]
        },
        {PK: "Country1", Prop2: "true", children:[
                {PK: "State2", Prop2: "true", children:[
                        {PK: "City2", Prop2: "Value2"}]
                }]
        },
        {PK: "Country1", Prop3: "true", children:[
                {PK: "State2", Prop3: "true", children:[
                        {PK: "City3", Prop3: "Value3"}]
                }]
       }]

and I am trying to merge them based on the PK property . Think of them as countries, states, and cities . Currently each object has a country, under its children property is a state and under it is a city. I want them to be merged such that if both objects have the same country, their states will be merged and if both states are the same, their cities will added together in the children property. Then, if a city has a property Prop1, the state should indicate it also has that property, hence the Prop1 = "true" . This also follows on the country level. To make it clearer, I am trying to make it look like this:

data = [{PK: "Country1", Prop1: "true", Prop2: "true", Prop3: "true" children:[
                {PK: "State1", Prop1: "true", children:[
                        {PK: "City1", Prop2: "Value1"}]
                },
                {PK: "State2", Prop2: "true", Prop3: "true", children:[
                        {PK: "City2", Prop2: "Value2"},
                        {PK: "City3", Prop3: "Value3"}]
                }]
       }]

I tried something like this but I can't wrap it around the children object which is also an array of objects. Can someone help me on this or lead me to a better answer. Thanks!

Here is a simple script using a custom merge functionality I've written sometime ago for json-easy-filter Hope it does the right stuff for you. See it in this plunk

var input = ... your data here ...

var groupByPk = function (arr) {
    var res = {};
    arr.forEach(function (node) {
        if (!res[node.PK]) {
            res[node.PK] = [
                node
            ];
        } else {
            res[node.PK].push(node);
        }
    });
    return res;
};

var mergeByPk = function (arr) {
    var groups = groupByPk(arr);
    var groups2 = [];

    for ( var pk in groups) {
        var group = groups[pk];
        var ress = merge.apply(this, group);
        groups2.push(ress.value);
    }
    return groups2;
};

var mergeData = function(data){
    var mergedCountries = mergeByPk(data);
    mergedCountries.forEach(function (country) {
        var mergedStates = mergeByPk(country.children);
        country.children = mergedStates;
        mergedStates.forEach(function (state) {
            var mergedCities = mergeByPk(state.children);
            state.children = mergedCities;
        });
    });
    return mergedCountries;
};

console.log(JSON.stringify(mergeData(input), null, 4));

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