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.
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;
}
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;
}
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.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With