-4

I'm trying to merge an object on a specific key (field is the key) but can't seem to find a way to do it. The images will better illustrate my problem.

enter image description here

enter image description here

What I'm trying to get is this...

0: {field: "currency", operator: "IN", values: ["GBP", "USD"]}
1: {field: "amount", operator: "IN", values: ["2", "3"]}
2: {field: "id", operator: "IN", values: ["12", "15"]}
Dally
  • 1,281
  • 4
  • 18
  • 37
  • 2
    Possible duplicate of [How can I merge properties of two JavaScript objects dynamically?](https://stackoverflow.com/questions/171251/how-can-i-merge-properties-of-two-javascript-objects-dynamically) – Hyyan Abo Fakher Jun 26 '18 at 14:59
  • Isn't the same mate – Dally Jun 26 '18 at 15:07

2 Answers2

1

Here the solution using lodash and uniqWith function: JSFiddle.

Here's the code:

function merge(array) {
  return _.uniqWith(array, compareAndMerge)
}

function compareAndMerge(first, second) {
    if (first.field === second.field) {
        first.values = second.values = [].concat(first.values, second.values)
        return true
    }
    return false
}


var data = [{
  field: 'Currency',
  operator: 'IN',
  values: ['usd']
}, {
  field: 'Currency',
  operator: 'IN',
  values: ['gbp']
}, {
  field: 'Amount',
  operator: 'IN',
  values: [2]
},
{
  field: 'Amount',
  operator: 'IN',
  values: [3]
}]

console.log(merge(data))

Lodash.uniqWidth function wants an array and a comparator. In case of equal fields we edit values of the two compared elements assigning the concatenation of the two values arrays.

Something more: it's a transgression to edit objects inside the comparator, but I think that it could run safely.

Paolo Dell'Aguzzo
  • 1,431
  • 11
  • 14
  • Hi mate, this has nearly solved it for me but it only works with two values. What if I have more than 3 currencies which is a possibility. – Dally Jun 27 '18 at 10:18
  • @Dally Are u thinking about this possibility: https://jsfiddle.net/r4ewdmt9/ ? It seems to work – Paolo Dell'Aguzzo Jun 27 '18 at 10:43
  • Fiddle doesn't seem to be working for me mate. I have lodash enabled. – Dally Jun 27 '18 at 11:56
  • Have you check the browser console? This is what it prints: [{"field":"Currency","operator":"IN","values":["abc","gbp","usd"]},{"field":"Amount","operator":"IN","values":[3,2]}] – Paolo Dell'Aguzzo Jun 27 '18 at 12:36
0

Sounds like you are looking to combine concepts of merging objects and concatenating arrays along the way.

Using vanilla ES6 (probably far from optimal in terms of performance):

const one = {field: "currency", values: ["USD"]};
const two = {field: "currency", values: ["GBP"]};

const mergeConcat = (obj1, obj2) => {
  const result = {...obj1, ...obj2};
  Object.keys(obj1).map(key => {
    if (Object.keys(obj2).includes(key) && Array.isArray(obj1[key])) {
      result[key] = obj1[key].concat(obj2[key]);
    }
  })
  return result;
}

console.log(mergeConcat(one, two))
// { field: 'currency', values: [ 'USD', 'GBP' ] }

Using lodash (almost directly from their docs):

const customizer = (objValue, srcValue) => {
  if (_.isArray(objValue)) {
    return objValue.concat(srcValue);
  }
}

const one = {field: "currency", values: ["USD"]};
const two = {field: "currency", values: ["GBP"]};

console.log(_.mergeWith(one, two, customizer))
// { field: 'currency', values: [ 'USD', 'GBP' ] }
Tadas Antanavicius
  • 4,882
  • 1
  • 20
  • 20