2

I'm trying to merge duplicate objects in a json array I received.

The array looks like this:

{
  modules: [{
    "name": "Weazel",
    "otherprop": ["a", "b"]
  }, {
    "name": "weazel",
    "otherprop": ["c", "b"]
  }]
}

For some reason I can't figure out how to merge the duplicates.

I have tried doing it by first mapping all the names to lowercase and then use unique, but that removes the values for otherprops.

let result = _.map(json.modules, mod => { mod.name = mod.name.tolower(); return mod; });
result = _.unique(result, 'name');

Is there anyone who knows how I can tackle my issue using lodash?

1
  • It's not really clear what otherprop should be after your merge. ['a','b','c']? ['a','b','c','b']? Commented Nov 8, 2016 at 12:00

4 Answers 4

3
var result = _.uniq(json.modules, function(item, key, a) { 
        return item.a;
    });

//Result : [{"name":"Weazel","otherprop":["a","b"]}]
Sign up to request clarification or add additional context in comments.

1 Comment

very short answer
1

You can achieve that using lodash's _.groupBy() with _.map() and _.mergeWith():

function mergeByName(arr) {
  return _(arr)
    .groupBy(function(item) { // group the items using the lower case
      return item.name.toLowerCase();
    })
    .map(function(group) { // map each group
      return _.mergeWith.apply(_, [{}].concat(group, function(obj, src) { // merge all items, and if a property is an array concat the content
        if (Array.isArray(obj)) {
          return obj.concat(src);
        }
      }))
    })
    .values() // get the values from the groupBy object
    .value();
}


var arr = {
  modules: [{
    "name": "Weazel",
    "otherprop": ["a", "b"]
  }, {
    "name": "weazel",
    "otherprop": ["c", "b"]
  }]
}

var result = mergeByName(arr.modules);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.6/lodash.min.js"></script>

Comments

1

Pure JS ES6 you might do as follows;

var modules = [{      "name": "Weazel",
                 "otherprop": ["a", "b"]
               },
               {      "name": "weazel",
                 "otherprop": ["c", "b"]
               },
               {      "name": "trix",
                 "otherprop": ["y", "z"]
               },
               {      "name": "trix",
                 "otherprop": ["x", "y"]
               }],
     result = [...modules.reduce(function(m,o){
                                   var name = o.name.toLowerCase();
                                        obj = m.get(name);
                                   return obj ? m.set(name,{     name: name,
                                                            otherprop: [...new Set(obj.otherprop.concat(o.otherprop))]
                                                           })
                                              : m.set(name,o);
                                 },new Map())
                         .values()];
console.log(result);

1 Comment

Great use of ES6 :)
0

I'm not sure about lodash or underscore, but for reference: a vanilla js solution. Might be nice to use a starting point and convert parts of it to their library-equivalents.

var json = {
  modules: [{
    "name": "Weazel",
    "otherprop": ["a", "b"]
  }, {
    "name": "weazel",
    "otherprop": ["c", "b"]
  }]
};

// The merge logic
var mergeModules = function(m1, m2) {
  // For example:
  return {
    name: m1.name,
    otherprop: (m2 ? m2.otherprop : [])
      .concat(m1.otherprop)
      .sort() // Note: add some sort of `uniques` method here as well
  };
};

// The 'normalize' key logic
var getModuleKey = function(mod) {
    return mod.name.toLowerCase();
};

// Create an object with a merged module for each unique key
var uniques = json.modules.reduce(function(map, current) {
  var key = getModuleKey(current); 
  map[key] = mergeModules(current, map[key]);
  return map;
}, {});

// Transform uniqes object ({ weasel: {}}) back to array: [{}]
var mergedArr = Object.keys(uniques).map(function(k) { return uniques[k]; });

console.log(mergedArr);
.as-console-wrapper { min-height: 100%; }

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.