Home > Enterprise >  Combine JSON objects bases on the same value
Combine JSON objects bases on the same value

Time:12-31

I’m looking for a way to combine JSON objects if they have the same address value in them. Building off this Combining JSON Question I have these two sample JSON files. Would love any suggestions thank you so much.

Before Combining:

[
    {
        "saleNo": "86131",
        "address": "6562 Dagmar Haven Suite 593 Warner Robins WI, 68085-5440",
        "deliveryTo": "Earl Bruen"
    },
    {
        "saleNo": "82483",
        "address": "6562 Dagmar Haven Suite 593 Warner Robins WI, 68085-5440",
        "deliveryTo": "Harold Kuhn"
    },
    {
        "saleNo": "53731",
        "address": "33194 Royal Track Suite 501 Enid CO, 57355",
        "deliveryTo": "Kristopher Bayer"
    },
    {
        "saleNo": "12285",
        "address": "183 Lazaro Meadow Suite 841 Council Bluffs AL, 52499",
        "deliveryTo": "Cassandra Mueller"
    },
    {
        "saleNo": "23404",
        "address": "89319 Witting Green Suite 924 Portland MN, 74633-9170",
        "deliveryTo": "Chris Thiel Sr."
    },
    {
        "saleNo": "70528",
        "address": "2410 Zaria Forges Suite 936 St. Louis GA, 94962-5376",
        "deliveryTo": "Glenda Larson"
    }
]
After Combining:

[
    {
        "saleNo": ["86131", "82483"],
        "address": "6562 Dagmar Haven Suite 593 Warner Robins WI, 68085-5440",
        "deliveryTo": ["Harold Kuhn", "Earl Bruen"]
    },
    {
        "saleNo": "53731",
        "address": "33194 Royal Track Suite 501 Enid CO, 57355",
        "deliveryTo": "Kristopher Bayer"
    },
    {
        "saleNo": "12285",
        "address": "183 Lazaro Meadow Suite 841 Council Bluffs AL, 52499",
        "deliveryTo": "Cassandra Mueller"
    },
    {
        "saleNo": "23404",
        "address": "89319 Witting Green Suite 924 Portland MN, 74633-9170",
        "deliveryTo": "Chris Thiel Sr."
    },
    {
        "saleNo": "70528",
        "address": "2410 Zaria Forges Suite 936 St. Louis GA, 94962-5376",
        "deliveryTo": "Glenda Larson"
    }
]
Sample Code:

let data = [
    {
        "saleNo": "86131",
        "address": "6562 Dagmar Haven Suite 593 Warner Robins WI, 68085-5440",
        "deliveryTo": "Earl Bruen"
    },
    {
        "saleNo": "82483",
        "address": "6562 Dagmar Haven Suite 593 Warner Robins WI, 68085-5440",
        "deliveryTo": "Harold Kuhn"
    },
    {
        "saleNo": "53731",
        "address": "33194 Royal Track Suite 501 Enid CO, 57355",
        "deliveryTo": "Kristopher Bayer"
    },
    {
        "saleNo": "12285",
        "address": "183 Lazaro Meadow Suite 841 Council Bluffs AL, 52499",
        "deliveryTo": "Cassandra Mueller"
    },
    {
        "saleNo": "23404",
        "address": "89319 Witting Green Suite 924 Portland MN, 74633-9170",
        "deliveryTo": "Chris Thiel Sr."
    },
    {
        "saleNo": "70528",
        "address": "2410 Zaria Forges Suite 936 St. Louis GA, 94962-5376",
        "deliveryTo": "Glenda Larson"
    }
]

let result = Object.values(data.reduce((c, {address,numbers}) => {
  c[address] = c[address] || {address,numbers: []};
  c[address].numbers = c[address].numbers.concat(Array.isArray(numbers) ? numbers : [numbers]); 
  return c;
}, {}));

console.log(result);

CodePudding user response:

So what about

let result = new Array();

for (let dataIndex = 0, dataMax = data.length; dataIndex < dataMax; dataIndex  ) {
    let address = data[dataIndex]["address"];

    let target = null;

    for (let resultIndex = 0, resultMax = result.length; resultIndex < resultMax; resultIndex  ) {
        if (result[resultIndex].address == address) {
            target = result[resultIndex];
            break;
        }
    }

    if (target == null) {
        result.push({ address: address, saleNo: new Array(), deliveryTo: new Array() });
        target = result[result.length - 1];
    }

    target.saleNo.push(data[dataIndex].saleNo);
    target.deliveryTo.push(data[dataIndex].deliveryTo);
}

not doing anything clever? Result is not exactly the desired result, because

  1. Fields saleNo and deliveryTo are always an Array even if there's just one value - you could adapt the example on first adding a string, and if it's not undefined, checking if it's an Array to simply add the new value, or otherwise replace the string with an Array that contains the first value. Not elegant, but easy to read/follow what's happening. Problem of course would be that on reading the result, you again have to handle this variance, instead of just always having an Array.

CodePudding user response:

This solution uses:

  • reduce to create a map of addresses, that contains maps of saleNo and deliveryTo (in order to weed out duplicates)
  • Object.entries and map to to convert the nested maps to the desired output

This reduce and map solution is faster than th enested for loops approach for large datasets, e.g. O(2n) vs. O(n*n)

let data = [ { "saleNo": "86131", "address": "6562 Dagmar Haven Suite 593 Warner Robins WI, 68085-5440", "deliveryTo": "Earl Bruen" }, { "saleNo": "82483", "address": "6562 Dagmar Haven Suite 593 Warner Robins WI, 68085-5440", "deliveryTo": "Harold Kuhn" }, { "saleNo": "53731", "address": "33194 Royal Track Suite 501 Enid CO, 57355", "deliveryTo": "Kristopher Bayer" }, { "saleNo": "12285", "address": "183 Lazaro Meadow Suite 841 Council Bluffs AL, 52499", "deliveryTo": "Cassandra Mueller" }, { "saleNo": "23404", "address": "89319 Witting Green Suite 924 Portland MN, 74633-9170", "deliveryTo": "Chris Thiel Sr." }, { "saleNo": "70528", "address": "2410 Zaria Forges Suite 936 St. Louis GA, 94962-5376", "deliveryTo": "Glenda Larson" } ]

let result = Object.entries(data.reduce((acc, obj) => {
  if(!acc[obj.address]) {
    acc[obj.address] = {
      saleNo: {},
      deliveryTo: {}
    };
  }
  acc[obj.address].saleNo[obj.saleNo] = true;
  acc[obj.address].deliveryTo[obj.deliveryTo] = true;
  return acc;
}, {})).map(arr => {
  let address = arr[0];
  let o = arr[1];
  return {
    saleNo: Object.keys(o.saleNo).sort(),
    address: address,
    deliveryTo: Object.keys(o.deliveryTo).sort()
  }
});

console.log(result);

  • Related