1

I have 2 objects array as follows:

arr1 =  [ { 'v1': 'abcde',
    'pv_45': 13018, 
    'geolocation': '17.340291,76.842807'
   }]

arr2 =[{ 'v1':'abcde',
    'pv_50': 13010,    
    geolocation: '17.340291,76.842807'
    }]

I want to merge the above 2 array int0 single based on condition that 'v1' and 'geolocation' should be same as follows:

[{'v1':'abcde',
      'pv_45': 13018, 
      'pv_50': 13010,
      'geolocation': '17.340291,76.842807'}]

I used _.extend, but its not checking any condition blindly it will merge. Please share your ideas. Thanks in advance.

Subburaj
  • 5,114
  • 10
  • 44
  • 87

4 Answers4

1

you can use underscore js union and uniq to do that.

var mergedArray = _.uniq(_.union(c1, c2), false, function(item, key, a){ return item; });
sachin.ph
  • 1,078
  • 12
  • 24
1

You could do the following:

var arr3 = [].concat.apply([], arr1, arr2);
var temp =_.groupBy(arr3, 'geolocation');
var result = Object.keys(_.groupBy(arr3, 'geolocation')).map(function(x)  {  return _.extend.apply(0, p[x]); })

if you prefer ES-6 arrow functions the result becomes

Object.keys(_.groupBy(arr3, 'geolocation')).map((x) => _.extend.apply(0, p[x]);)
Hrishi
  • 7,110
  • 5
  • 27
  • 26
1

Using pure JavaScript it could be done like this:

var arr1 =  [ { 'v1': 'abcde',
    'pv_45': 13018, 
    'geolocation': '17.340291,76.842807'
  }],
  arr2 =[{ 'v1':'abcde',
    'pv_50': 13010,    
    geolocation: '17.340291,76.842807'
  }],
  mergeOnV1Geo = function (arr1, arr2) {
    var mergeObj = {},
      merge = function (item) {
        var key = item.v1 + ',' + item.geolocation;
        // if this is the first object with this key
        // create a new object and copy v1, geolocation info
        if (!mergeObj[key]) {
          mergeObj[key] = {
            v1: item.v1,
            geolocation: item.geolocation
          };
        }
        // add other props
        Object.keys(item).forEach(function (prop) {
          if (!prop.match(/v1|geolocation/)) {
            mergeObj[key][prop] = item[prop];
          }
        });
      };
    arr1.forEach(merge);
    arr2.forEach(merge);

    // map back into an array
    return Object.keys(mergeObj).map(function (key) {
      return mergeObj[key];
    });

  };

mergeOnV1Geo(arr1, arr2);
Useless Code
  • 12,123
  • 5
  • 35
  • 40
  • Thanks for your valuable time. I have this logic code with me. But i need some efficient way to accomplish this. – Subburaj Apr 22 '15 at 11:47
  • I don't know if you can get much more efficient. This code make a single pass over each input array and then one more pass over the merged data to convert it back into an array. – Useless Code Apr 22 '15 at 12:01
  • @ Useless Code suppose consider that the array of different length. What would happen?? – Subburaj Apr 22 '15 at 12:04
  • The length of the arrays doesn't matter. If they are different lengths the code would act exactly the same. `merge` is run once for each item in the input arrays and then `mergeObj` is converted to an array. Longer arrays would take more time to complete but that would happen with any method you use. Using Underscore, each Underscore method you use will make at least one pass over the data. You might be able to write it with less code using Underscore but it will probably be less efficient in terms of performance. – Useless Code Apr 22 '15 at 12:36
0

ES6: Using spread operator and reduce.

arr1 =  [{ v1: 'abcde',
  pv_45: 13018, 
  geolocation: '17.340291,76.842807'
}]

arr2 =[{ v1:'abcde',
  pv_50: 13010,    
  geolocation: '17.340291,76.842807'
}]

// Keys to be grouped i.e whose values should be equal
groupableKeys = ['v1', 'geolocation'];

// Reducer that creates an Object with Key as the
// groupable key values value1::value2 and Value as
// the list of objects whose v1 and geolocation are same
groupableReducer = (a, b) => {
  const uniqKey = groupableKeys.map(key => b[key]).join("::");
  a[uniqKey] = [...(a[uniqKey] || []), b];
  return a;
}

// Merges two objects using the spread operator
mergableReducer = (a, b) => ({...a, ...b})

// Merge two arrays and start processing
groupableKeyObject = [...arr1, ...arr2].reduce(groupableReducer, {})

output = Object.keys(groupableKeyObject)
               .map(key => 
                   groupableKeyObject[key].reduce(mergableReducer, {})
                )

console.log(output);
Nandu Kalidindi
  • 6,075
  • 1
  • 23
  • 36