SUBSCRIBE VIA RSS


Subscribe to our feed

Symfony Experts

Symfony Experts
If you have an urgent question for a symfony-related issue, this is the place to ask.

Topics

Stack Overflow


The old fashioned way

RECENT TUNES

July 19, 2007 – 2:36am Javascript Array Merge: array_merge

Using protoype.js I discovered a quick way to merge to arrays in javascript:

function array_merge(one, two) {
  one.push(two);
  return one.flatten();
}

This definitely beats the alternative of iterating through the second array by hand and adding it to the first. Any comments or suggestions are welcome.

Posted by in  Web Development   |  

9 Responses to Javascript Array Merge: array_merge

  1. Rumble says:

    You can do this even quicker!

    one = one.concat(two);

    Job done!

  2. Mrsoul says:

    Another example for merge:

    function array_merge(arr) {
    	var merged = arr;
    	for (var i = 1; i < arguments.length; i++) {
    		merged = merged.concat(arguments[i]);
    	}
    	return merged;
    }
     
    arr4 = array_merge(arr1, arr2, arr3);
  3. Subhasis Deb says:

    Following is my version of independent array_merge (compact):

    /***
    * Simulate php array_merge function
    *
    ... [more] * @param {Object/Array} arr1
    * @param {Object/Array} arr2
    * var a1 = {'aa':100, 'bb':2, 'cc':[6,7], 'dd':[12,13], 'ee':{'15':15,'16':16}};
    * var b1 = {'xx':101, 'bb':5, 'cc':8, 'dd':[14,15], 'ee':{'17':17,'18':18}};
    * var c = array_merge(a1, b1);
    * console.log(c) [in firebug]
    * Output: {'aa':100, 'bb': 5, 'cc':[6,7], 'dd':[12,13,14,15], 'ee':{'15':15,'16':16,'17':17,'18':18}, 'xx':101}
    */
    var array_merge = function(arr1, arr2){
      if((arr1 && (arr1 instanceof Array)) && (arr2 && (arr2 instanceof Array))){
        for (var idx in arr2) {
          arr1.push(arr2[idx]);
        }
      }else if((arr1 && (arr1 instanceof Object)) && (arr2 && (arr2 instanceof Object))){
        for(var idx in arr2){
          if(idx in arr1){
            if (typeof arr1[idx] == 'object' && typeof arr2 == 'object') {
              arr1[idx] = array_merge(arr1[idx], arr2[idx]);
            }else{
              arr1[idx] = arr2[idx];
            }
          }else{
            arr1[idx] = arr2[idx];
          }
        }
      }
      return arr1;
    }
  4. Scott Meves says:

    @Subhasis Deb: Thanks! Sorry our comment code formatting is so messed up.

  5. gregory says:

    I have a prototype that handles more complex merging of arrays as well as inserting arrays into other arrays all without needing a for / while loops. Read more about it here: http://gregorytomlinson.com/encoded/2008/12/25/javascript-array-merge/

  6. Andrew Noyes says:

    I like how Subhasis Deb’s function differentiates between Arrays and Objects, since Objects functionally simulate PHP associative arrays, and more often than not are what I use for handling data. However, there are a few things I would recommend changing. First of all, the for…in loop pattern is incredibly inefficient with arrays, and I also never recommend using it for readability purposes. I switch between JavaScript and PHP all the time, and in PHP, we have the notation foreach ($var as $arr) to loop through the array, where $var is the value of the current iteration. However, in JavaScript, the for…in notation simply initializes an index. This isn’t a big deal if you work with JavaScript all the time, but I’ve been tripped up by more than one loop where I was expecting the val in for (var val in myArr) to be equal to one of myArr’s values, rather than an interator. Secondly, rather than using a loop, you can use concat, which is a native method and nearly infinitely faster than using a JavaScript loop.

    There is one major bug in this function if you’re scripting in a multi-frame DOM environment. Objects in different windows do not share their constructor with the objects in the window that spawned them, so the evaluation [].constructor == Array is actually false in child windows. Since this check is false, the next check asks if the arguments are an instance of Object, which is always true since everything is an Object in JavaScript.(i.e. [] instanceof Object evaluates true). The solution to this is to call the constructor in the context of the global Object object using the apply method:

    Object.prototype.toString.apply([]); // == “[object Array]”

    This also leaves out array-like values, which are very important in DOM scripting, since document.getElementsByTagName doesn’t return an Array, it returns a NodeList, which is not an instanceof Array. Because of these array-like objects, Arrays are part of a broader group of objects called Collections. For this, I picked up this handy check from the YUI source code to check if an element is a collection (Arrays included):

    function isValidCollection(obj) {
        try {
            return (
                obj &&    // Element exists
                typeof obj != "string" &&    // Weeds out strings for length test
                obj.length &&
                !obj.tagName &&    // Isn't an HTML node
                !obj.alert &&    // not window
                typeof obj[0] != "undefined"     // Has at least one element
            );
        } catch (e) {
            return false;
        }
    }

    I might rewrite this function to be sensitive to array-like objects and be a little more compatible with multi-frame environments.

  7. Andrew Noyes says:

    Here’s my take on array_merge for JavaScript:

    http://gist.github.com/102384

    For better or for worse, it allows collections to be merged into arrays. It checks the type of the objects strongly to make sure they’re compatible. It works fine in Firefox and Safari that I know of.

  8. MC says:

    I didn’t test this solution for performances, but if you are looking for a simpler way to do it :

    function array_merge(one, two) {
    one.push.apply(one, two);
    }

    array_merge(one.clone(), two) avoids the side-effect