9

jsfiddle link: http://jsfiddle.net/vN6fn/1/

Assume I have these 2 objects:

var obj1 = { data: [ 
                      {id:1, comment:"comment1"},
                      {id:2, comment:"comment2"},
                      {id:3, comment:"comment3"}
                   ] }

var obj2 = { data: [ 
                      {id:2, comment:"comment2"},
                      {id:3, comment:"comment3"},
                      {id:4, comment:"comment4"}
                   ] }

And final object should look like this:

var final = { data: [ 
                      {id:1, comment:"comment1"},
                      {id:2, comment:"comment2"},
                      {id:3, comment:"comment3"},
                      {id:4, comment:"comment4"}
                   ] }

Here are some things to consider:

  • obj1 and obj2 may or may not have duplicates

$.extend() replaces objects, $.merge() doesn't remove duplicates (I know I can do for loop, but I'm looking for a better way to do this).

Sherzod
  • 5,041
  • 10
  • 47
  • 66
  • 1
    Wouldn't preserving the order mean ( 3, 4, 5, 1, 2 ), since object 1 is first? – Šime Vidas Feb 03 '12 at 20:03
  • sorry to confuse you, I can change the numbering of objects. – Sherzod Feb 03 '12 at 20:07
  • @shershames Hm, that didn't clear my confusion. What do you mean by that? – Šime Vidas Feb 03 '12 at 20:12
  • There's no way to do this without some sort of loop. This question may also be a duplicate of http://stackoverflow.com/questions/3629817/getting-a-union-of-two-arrays-in-jquery – David Titarenco Feb 03 '12 at 20:21
  • @ŠimeVidas I updated the question. Let me know if it still doesn't make sense. – Sherzod Feb 03 '12 at 20:22
  • There is no way to do this without your own loop because `{} !== {}`. – gen_Eric Feb 03 '12 at 20:25
  • @DavidTitarenco Union of arrays and union of objects is not the same thing. The question title might be better stated as "How to merge two JSON objects - removing duplicates and preserving order in Javascript/jQuery?" – sinemetu1 Feb 03 '12 at 20:53
  • 1
    @sgarrett: But the question is, in fact, "how to merge two arrays," ergo, may be a duplicate of the aforementioned question. Maybe the OP is not exactly sure how to approach the problem. I just did a search and a question with an almost equivalent title came up. Take it for what it's worth. – David Titarenco Feb 03 '12 at 20:59

4 Answers4

14

You can use $.merge and then go through and remove duplicates, and then sort it.

$.merge(obj1.data, obj2.data);

var existingIDs = [];
obj1.data = $.grep(obj1.data, function(v) {
    if ($.inArray(v.id, existingIDs) !== -1) {
        return false;
    }
    else {
        existingIDs.push(v.id);
        return true;
    }
});

obj1.data.sort(function(a, b) {
    var akey = a.id, bkey = b.id;
    if(akey > bkey) return 1;
    if(akey < bkey) return -1;
    return 0;
});
gen_Eric
  • 223,194
  • 41
  • 299
  • 337
4

Here is a straight jQuery solution:

function mergeDeep(o1, o2) {
    var tempNewObj = o1;

    //if o1 is an object - {}
    if (o1.length === undefined && typeof o1 !== "number") {
        $.each(o2, function(key, value) {
            if (o1[key] === undefined) {
                tempNewObj[key] = value;
            } else {
                tempNewObj[key] = mergeDeep(o1[key], o2[key]);
            }
        });
    }

    //else if o1 is an array - []
    else if (o1.length > 0 && typeof o1 !== "string") {
        $.each(o2, function(index) {
            if (JSON.stringify(o1).indexOf(JSON.stringify(o2[index])) === -1) {
                tempNewObj.push(o2[index]);
            }
        });
    }

    //handling other types like string or number
    else {
        //taking value from the second object o2
        //could be modified to keep o1 value with tempNewObj = o1;
        tempNewObj = o2;
    }
    return tempNewObj;
};

Demo with complex objects. I have turned this into a blog-post showing the difference between jQuery's .extend() and my script here.

sinemetu1
  • 1,726
  • 1
  • 13
  • 24
1

http://jsfiddle.net/J9EpT/

function merge(one, two){
  if (!one.data) return {data:two.data};
  if (!two.data) return {data:one.data};
  var final = {data:one.data};
  // merge
  for(var i = 0 ; i < two.data.length;i++){
      var item = two.data[i];
      insert(item, final);
  }
  return final;
}


function insert(item, obj){
    var data = obj.data;
    var insertIndex = data.length;
    for(var i = 0; i < data.length; i++){
        if(item.id == data[i].id){
           // ignore duplicates
           insertIndex = -1;
           break;
        } else if(item.id < data[i].id){
           insertIndex = i;
           break;
        }
    }
    if(insertIndex == data.length){
        data.push(item);
    } else if(insertIndex != -1) {
        data.splice(insertIndex,0,item);
    }
}

var final = merge(obj1, obj2);
driangle
  • 11,601
  • 5
  • 47
  • 54
0

Merge two array of objects removing duplicates

  • Using Es6 map() and filter() method

var obj1 = { data: [ 
                      {id:1, comment:"comment1"},
                      {id:2, comment:"comment2"},
                      {id:3, comment:"comment3"}
                   ] }

var obj2 = { data: [ 
                      {id:2, comment:"comment2"},
                      {id:3, comment:"comment3"},
                      {id:4, comment:"comment4"}
                    ]}
let obj3 = [...obj1.data, ...obj2.data]

function mergeUniqueArray(arr, comp) {

  let unique = arr
    .map(item => item[comp])

     // store the keys of the unique objects
    .map((item, i, final) => final.indexOf(item) === i && i)

    // eliminate the duplicate keys & store unique objects
    .filter(item => arr[item]).map(item => arr[item]);
    
   return unique;
}

console.log(mergeUniqueArray(obj3,'id'));
akhtarvahid
  • 9,445
  • 2
  • 26
  • 29