views:

84

answers:

2

I want to merge two Array's in JavaScript. Unfortunately, comparisons of the particular data I am using is expensive. What is the best algorithm to merge my to lists with the least amount of comparisons?

EDIT: I should note that the two Array's are sorted and I would like the merged content to be sorted and have only unique values.

EDIT: By request I will give you my current code, but it really doesn't help..

// Merges arr1 and arr2 (placing the result in arr1)
merge = function(arr1,arr2) {
    if(!arr1.length) {
        Array.prototype.push.apply(arr1,arr2);
        return;
    }
    var j, lj;
    for(var s, i=0, j=0, li=arr1.length, lj=arr2.length; i<li && j<lj;) {
        s = compare(arr1[i], arr2[j]);
        if(s<0) ++i;
        else if(s==0) ++i, ++j;
        else arr1.splice(i,0, arr2[j++]);
    }
    if(j<lj) Array.prototype.push.apply(arr1, arr2.slice(j));
};
+1  A: 

This is exactly what merge sort does in the merging step with a minor addition that duplicate elements will be dropped off. Here's the algorithm:

function merge(left,right)
    var list result
    while length(left) > 0 and length(right) > 0
        if first(left) ≤ first(right)
            append first(left) to result
            left = rest(left)
        else
            append first(right) to result
            right = rest(right)
    end while
    if length(left) > 0 
        append left to result
    else  
        append right to result
    return result
Anurag
Yes, merge sort is exactly what I was basing this off of. The comparisons in this merge function (see my version above) are slowing the entire thing down considerably, so I would like an algorithm with fewer comparison calls.
jairajs89
The question cannot be answered without knowing about what that data is. If comparison is the slower step then I can just suggest you to eliminate it altogether, but I can't as I don't know how else would it be done. Also, are you sure that `compare` is the more expensive step and not `splice`, because `splice` will not only insert the element, but fix the index of each element occurring after.
Anurag
A: 

Here is a function to make the array unique:

Array.prototype.unique = function () {
    var r = new Array();
    o:for(var i = 0, n = this.length; i < n; i++)
    {
        for(var x = 0, y = r.length; x < y; x++)
        {
            if(r[x]==this[i])
            {
                continue o;
            }
        }
        r[r.length] = this[i];
    }
    return r;
}

To merge Arrays you would do:

var MainArray= arr1.concat(arr2);

Then to remove duplicates:

var MainArray= MainArray.unique();

Then to sort:

var MainArray= MainArray.sort(); //Or you own sort if you have one

I think this sounds along the lines you were looking for, but it might depend on the amount and type of data.