2

I'm a javascript beginner and I'm trying to merge two arrays.

I have two arrays like this:

 arr1[
{
        description : "this is a object",
        array       : ["a","b"]
 }
    ]

 arr2[
{
       array : ["c","d"]
} 
   ]

And I want to get a resulting javascript object like this

result = { description : "this is a object", array : ["a","b","c","d"]}

The order of elements isn't important to me. So I tried the following.

result = $.extend(true, {},arr1,arr2)[0];

But this returns the following output

result = { description : "this is a object", array : ["c","d"] }

Which isn't what I want the result to be since it's missing values. How can I merge them the way I want?

SuperBiasedMan
  • 8,997
  • 9
  • 43
  • 66
qualitytest
  • 545
  • 1
  • 7
  • 17

2 Answers2

3

You're confusing arrays and hashes. The presence of the colon separator in your "arrays" suggests you're trying to define hashes. Hashes must be delimited by braces {} rather than square brackets [].

Assuming you're trying to define and combine two hashes, here's how it could be done without any genericity, IOW by explicitly specifying how to incorporate each key/value pair from each input hash into the combined hash:

var obj1 = {
    description : "this is an object",
    array       : ["a","b"]
};

var obj2 = {
    array : ["c","d"]
};

var res = {
    description : obj1.description,
    array       : obj1.array.concat(obj2.array)
};

alert(res.description); // "this is an object"
alert(res.array); // a,b,c,d

Now, for a more general solution, you can code "standard" logic for how to handle various data types and their collisions in the input pair of hashes:

var obj1 = {
    description : "this is an object",
    array       : ["a","b"]
};

var obj2 = {
    array : ["c","d"]
};

function combine(obj1,obj2) {
    var res = {};
    for (var k1 in obj1) {
        if (!obj1.hasOwnProperty(k1)) continue;
        if (obj2.hasOwnProperty(k1)) { // collision
            if (typeof(obj1[k1]) !== typeof(obj2[k1])) throw "type mismatch under key \""+k1+"\".";
            if (Array.isArray(obj1[k1])) {
                res[k1] = obj1[k1].concat(obj2[k1]);
            } else if (typeof(obj1[k1]) === 'string' || obj1[k1] instanceof String) {
                res[k1] = obj1[k1]+obj2[k1];
            } else if (typeof(obj1[k1]) === 'object') {
                res[k1] = combine(obj1[k1],obj2[k1]);
            } else {
                throw "unsupported collision type "+typeof(obj1[k1])+" under key \""+k1+"\".";
            }
        } else {
            res[k1] = obj1[k1];
        }
    }
    for (var k2 in obj2) {
        if (!obj2.hasOwnProperty(k2)) continue;
        if (obj1.hasOwnProperty(k1)) continue; // already handled it above
        res[k2] = obj2[k2];
    }
    return res;
}

var res = combine(obj1,obj2);

alert(res.description); // "this is an object"
alert(res.array); // a,b,c,d

Following your edit, my solutions are still applicable; you just have to index the arrays first to extract the contained objects. So here would be the revised implementation:

Solution 1:

var res = {
    description : arr1[0].description,
    array       : arr1[0].array.concat(arr2[0].array)
};

Solution 2:

var res = combine(arr1[0],arr2[0]);
bgoldst
  • 30,505
  • 4
  • 34
  • 59
  • Thank you for your correction. Let me correct it. It is basically an object within an array. I am dealing with something like this arr1[ { description : "this is a object", array : ["a","b"] } ] Also the array : ["a", "b"] gets added dynamically, So when i try to refer to it as arr1[0].array it gives me error. Please help – qualitytest Aug 06 '15 at 08:52
  • @qualitytest See my edit. With respect to your comment about the dynamism of the `array` hash entry, that is a separate issue. At the moment the above code runs in the context of your page, either the `array` entry is present in the hash or it is not; that depends on the larger design of your page. If the entry is present, then `arr1[0].array` will not fail. If it is not present, then my first solution would fail, because it explicitly references `arr1[0].array`, but my second solution would not fail, because it only works with the existing entries in the input hashes. – bgoldst Aug 06 '15 at 09:10
  • But i just noticed, it shows duplicate elements in the nested array. :( Please help – qualitytest Aug 06 '15 at 10:01
  • The [`Array.prototype.concat()`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) function does not remove duplicates. You'll have to add code if you want to do so. I don't know of any easy built-in way to remove duplicates from an array in JavaScript; see http://stackoverflow.com/questions/9229645/remove-duplicates-from-javascript-array for some options. – bgoldst Aug 06 '15 at 10:08
  • i used this https://stackoverflow.com/questions/1584370/how-to-merge-two-arrays-in-javascript-and-de-duplicate-items and it helped. Thanks again! :) – qualitytest Aug 07 '15 at 02:04
0

Perhaps you should take a look at this implementation of a recursive merge function.

It should have the same behavior as the PHP array_merge_recursive.

code:

function array_merge_recursive(arr1, arr2) {
  //  discuss at: http://phpjs.org/functions/array_merge_recursive/
  // original by: Subhasis Deb
  //    input by: Brett Zamir (http://brett-zamir.me)
  // bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  //  depends on: array_merge
  //   example 1: arr1 = {'color': {'favourite': 'read'}, 0: 5}
  //   example 1: arr2 = {0: 10, 'color': {'favorite': 'green', 0: 'blue'}}
  //   example 1: array_merge_recursive(arr1, arr2)
  //   returns 1: {'color': {'favorite': {0: 'red', 1: 'green'}, 0: 'blue'}, 1: 5, 1: 10}

  var idx = '';

  if (arr1 && Object.prototype.toString.call(arr1) === '[object Array]' &&
    arr2 && Object.prototype.toString.call(arr2) === '[object Array]') {
    for (idx in arr2) {
      arr1.push(arr2[idx]);
    }
  } else if ((arr1 && (arr1 instanceof Object)) && (arr2 && (arr2 instanceof Object))) {
    for (idx in arr2) {
      if (idx in arr1) {
        if (typeof arr1[idx] === 'object' && typeof arr2 === 'object') {
          arr1[idx] = this.array_merge(arr1[idx], arr2[idx]);
        } else {
          arr1[idx] = arr2[idx];
        }
      } else {
        arr1[idx] = arr2[idx];
      }
    }
  }

  return arr1;
}
GottZ
  • 4,318
  • 1
  • 30
  • 42
Pascal
  • 2,007
  • 3
  • 32
  • 49
  • even though i like the idea, the linked code will override members of arr1. the original php function will not do that. instead it will only return the merged array. this ported function does not need a return statement at all since, after running this function, the return value has the same content as the first argument. – GottZ Aug 06 '15 at 09:06
  • in addition: you will need array_merge aswell. not only that.. array_merge_recursive and array_merge have to be members of the same object. i guess you'd need to do something like this: `var phpjs={};phpjs.prototype={array_merge:array_merge,array_merge_recursive:array_merge_recursive};` wich results in function calls like: `var mergedArray = phpjs.array_merge_recursive(arr1, arr2);` – GottZ Aug 06 '15 at 09:14