Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cleanly merge two arrays in ActionScript (3.0)?

What's a nice way to merge two sorted arrays in ActionScript (specifically ActionScript 3.0)? The resulting array should be sorted and without duplicates.

like image 491
mellis Avatar asked Dec 02 '08 20:12

mellis


4 Answers

To merge (concatenate) arrays, use .concat().

Below are two examples of how you can concatenate arrays and remove duplicates at the same time.

More convenient way: (you can use ArrayUtil.createUniqueCopy() from as3corelib)

// from as3corelib:
import com.adobe.utils.ArrayUtil;

var a1:Array = ["a", "b", "c"];
var a2:Array = ["c", "b", "x", "y"];

var c:Array = ArrayUtil.createUniqueCopy(a1.concat(a2)); // result: ["a", "b", "c", "x", "y"]

Slightly faster way: (you can loop through the arrays yourself and use Array.indexOf() to check for duplicates)

var a1:Array = ["a", "b", "c"];
var a2:Array = ["c", "b", "x", "y"];
var a3:Array = ["a", "x", "x", "y", "z"];

var c:Array = arrConcatUnique(a1, a2, a3); // result: ["a", "b", "c", "x", "y", "z"]

private function arrConcatUnique(...args):Array
{
    var retArr:Array = new Array();
    for each (var arg:* in args)
    {
        if (arg is Array)
        {
            for each (var value:* in arg)
            {
                if (retArr.indexOf(value) == -1)
                    retArr.push(value);
            }
        }
    }
    return retArr;
}
like image 144
hasseg Avatar answered Oct 01 '22 23:10

hasseg


This is kind of an simple algorithm to write. I would be surprised if there were a more direct way to do this in Actionscript.

function merge(a1:Array, a2:Array):Array {
    var result:Array = [];
    var i1:int = 0, i2:int = 0;

    while (i1 < a1.length && i2 < a2.length) {
        if (a1[i1] < a2[i2]) {
            result.push(a1[i1]);
            i1++;
        } else if (a2[i2] < a1[i1]) {
            result.push(a2[i2]);
            i2++;
        } else {
            result.push(a1[i1]);
            i1++;
            i2++;
        }
    }

    while (i1 < a1.length) result.push(a1[i1++]);
    while (i2 < a2.length) result.push(a2[i2++]);

    return result;
}
like image 33
Tmdean Avatar answered Oct 02 '22 00:10

Tmdean


Using Array.indexOf to detect duplicates is going to be painfully slow if you have a List containing a large number of elements; a far quicker way of removing duplciates would be to throw the contents of the Array into a Set after concatenating them.

// Combine the two Arrays.
const combined : Array = a.concat(b);

// Convert them to a Set; this will knock out all duplicates.
const set : Object = {};  // use a Dictionary if combined contains complex types.

const len : uint = combined.length;
for (var i : uint = 0; i < len; i++) {
    set[combined[i]] = true;
}

// Extract all values from the Set to produce the final result.
const result : Array = [];
for (var prop : * in set) {
    result.push[prop];
}

If your program makes heavy use of Collections then if may be prudent to make use of one of the many AS3 Collections frameworks out there which provide a simple interface for manipulating data and will always take the optimal approach when it comes to the implementation.

  • AS3Commons Collections
  • Polygonal DS
like image 36
JonnyReeves Avatar answered Oct 02 '22 00:10

JonnyReeves


function remDuplicates(_array:Array):void{
    for (var i:int = 0; i < _array.length;++i) {
        var index:int = _array.indexOf(_array[i]);
        if (index != -1 && index != i) {
            _array.splice(i--, 1);
        }
    }
}

Then for the "merge" use concat. exemple :

var testArray:Array = [1, 1, 1, 5, 4, 5, 5, 4, 7, 2, 3, 3, 6, 5, 8, 5, 4, 2, 4, 5, 1, 2, 3, 65, 5, 5, 5, 5, 8, 4, 7];
var testArray2:Array = [1, 1, 1, 5, 4, 5, 5, 4, 7, 2, 3, 3, 6, 5, 8, 5, 4, 2, 4, 5, 1, 2, 3, 65, 5, 5, 5, 5, 8, 4, 7];

testArray.concat(testArray2);
trace(testArray);
remDuplicates(testArray);
trace(testArray);
like image 37
raph Avatar answered Oct 01 '22 22:10

raph