0

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!

11
  • 3
    Please use the term JSON appropriately. These are Javascript objects. JSON is a text interchange format which this is not. Commented Oct 20, 2014 at 23:14
  • 1
    What do you expect to do in the result if multiple objects you are merging have conflicting values for children with the same key. Can children go to any depth or are you just trying to merge the first level of the children property? And the result should remove the digits from the PK key so "A1" becomes "A"? A lot more help on how the merge algorithm should work is needed. Commented Oct 20, 2014 at 23:16
  • @jfriend00 - Thanks for pointing that out. Sorry. I edited the Objects to give a clearer picture of the problem. Think of it as a country with a set of states and each states have a set of cities. I want to merge all the cities under the same state and all the states under the same country. Commented Oct 21, 2014 at 0:42
  • But, how do you decide which properties on the first level of children to copy up to the top? In your example, you are copying "PropN" properties, but not the "PK" property. How to decide what to copy is still unclear. And, in your latest comment, this is now multi-level so you want to do this recursively at more than just one level? Commented Oct 21, 2014 at 0:46
  • 1
    I took a shot at it, but didn't quite get there because it turns out that what you want is not a pure recursive merge. I still don't quite understand the rules. I'm out of time to work on it, but here's what I had so far: jsfiddle.net/jfriend00/vz718yuL. It merges the top level correctly, but not the lower levels. Commented Oct 21, 2014 at 2:26

1 Answer 1

0

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));
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.