How to remove element from array A that are also in array B in Actionscript 3.0? - actionscript-3

Suppose I have array A and array B which contains object. How do I "clean" elements from array A that are also exist in B. That is, I need to remove all element in A that are also in B.

From my understanding, you're trying to remove all similar items from array A that are present in B?
for (var i:uint = 0; i < arrayB.length; i++) {
arrayA.splice(arrayA.indexOf(arrayB[i]), 1);
}
Do note this only removes ONE of each item in arrayA. If you have multiple of the same instances in arrayA that are present in arrayB, only one will be removed. For multiples of the same instances, use this instead:
for (var i:uint = 0; i < arrayB.length; i++) {
while(arrayA.indexOf(arrayB[i]) >= 0) {
arrayA.splice(arrayA.indexOf(arrayB[i]), 1);
}
}

This effectively removes every element of Array B that happen to occur in Array A;
for each (var anItem:Object in B)
{
var anIndex:int;
do
{
anIndex = A.indexOf(anItem);
A.splice(anIndex, 1);
}
while (anIndex > -1);
}

Related

Make 2d array from single array

I created a level editor for web game, I can build, save, load and play levels.
Now I want to edit some levels but I have a weird situation.
I export a level as a single array, it looks like this 3,4,5,5,7,89,4,2,1...and those numbers represent frames. (tile-based).
Now if I want to edit this level and save it again, I need a level to be described as multidimensional array.
Actually, when I save the level I have a string that describes my map, then I convert string to array.
So can you tell me (if possible), how to convert this array1 (or string) to array2?
Lets say I have only 25 tiles (map from level editor is array1)
array1 =
1,1,1,1,1,
2,2,2,2,2,
3,3,3,3,3,
4,4,4,4,4,
5,5,5,5,5
I need this:
array2 =
[
[1,1,1,1,1],
[2,2,2,2,2],
[3,3,3,3,3],
[4,4,4,4,4],
[5,5,5,5,5]
];
UPDATE:
So I need 2d array to build level container.
I do not have experience with tile based games, but here you can see what I do.
Let's say I have 2d array and this is how I create a new level container:
for (i = 0; i < array2.length; i++)
{
for (var j = 0; j < array2[i].length; j++)
{
tile = new Tile();
tile.name = "" + i + j;
tile.x = j * tile.width;
tile.y = i * tile.height;
levelContainer.addChild(tile);
tile.gotoAndStop(array2[i][j]+1);
tile.addEventListener(MouseEvent.MOUSE_DOWN,
buildingLeve);
}
}
addChild(levelContainer);
I have tried to get 2d array from single array as Rudolfwm and Marcela suggested, but when I want to edit a level container using new array2, my tiles go on wrong frames.
For example, if correct frame is 1, tile goes to frame 11,
This code above (building level) works if I create my own 2d array, but not if I convert string to 2d array as suggested.
Try array1[x+y*row] which gives the same result as copying all your data to array2[x][y].
Or if you insist on 2d arrays:
var array2 = new Array(row);
for (var y = 0; y < row; y++) {
array2 [y] = new Array(column);
for(var x=0; x < column; x++) {
array2 [y][x]=array1[x+y*row];
}
}
You start with a String and convert that into an Array using String.split().
Once you have a temporary array, you use a nested loop to populate the final array (arr21).
var row:int = 5;
var column:int = 5;
var arr1:String = "1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5";
var tempArr:Array = arr1.split(',');
var arr2:Array = [];
for(var i:int = 0; i < row; i++)
{
arr2[i] = []; // create a new row array
for(var j:int = 0; j < column; j++)
{
// grab the first item from the temp array and push it onto the row array
arr2[i].push(tempArr.shift());
}
}
NOTE: This is not optimized, and could become quite laggy with larger level maps. This is just to give you an idea of where you can start.

ActionScritp 3 removeChild in loop

I have two arrays, fireballs and gombas (enemies).
When I create fireball and gomba, I add them into arrays using push();
I shoot fireballs and move gombas using foor loop
for (var f:int = 0; f < fireballs.length; f++)
{
// move fireballs
}
I also remove fireballs if it goes too far, for example
if (myFireball.x + 1000 < player.x)
{
if (myFireball.parent)
{
myFireball.parent.removeChild(myFireball);
fireballs.splice(myFireball, 1);
}
}
I have no problem removing fireballs, but if fireball hitTestObject gomba, I want to remove both, fireball and gomba, ant thats my problem.
I tried on this way and I get error, a term is undefined and has no properties
for (i = 0; i < fireballs.length; i++)
{
for (var m = 0; m < gombas.length; m++)
{
if (fireballs[i].hitTestObject(gombas[m]))
{
if (fireballs[i].parent)
{
fireballs[i].parent.removeChild(fireballs[i]);
// same for gombas
}
}
}
}
If I use same loop but just check if fireballs and gombas are visible, if fireballs hit gombas I set visible to false and it works ok. Why it wont work with removeChild.
As #itcouldevenbeaboat says, when looping through an array and removing objects, it's better to loop backwards; that way, you won't have index issues.
For example, with the array ["one","two","three"], if you looped through and removed like so:
for( var i:int = 0; i < myArray.length; i++ )
myArray.splice( i, 1 );
What's happening, is this:
i starts at 0, which points to "one"
we remove the object at position 0 from myArray
myArray is now ["two","three"]
at the end of the loop, i is incremented, and becomes 1
we start the next iteraction, and i is 1, which points to "three"
In this example, we've skipped over the "two" String, because the splice has modified the array we're iterating. If we went backwards:
for( var i:int = myArray.length - 1; i >= 0; i-- )
myArray.splice( i, 1 );
Then we get this:
i starts at 2, which points to "three"
we remove the object at position 2 from myArray
myArray is now ["one","two"]
at the end of the loop, i is decremented, and becomes 1
we start the next iteraction, and i is 1, which points to "two"
Thus we remove all the objects from myArray, no problem.
For your particular example, as you're removing objects from the two arrays, you should iterate backwards, which should give you something like:
outer: for ( var i:int = fireballs.length - 1; i >= 0; i-- )
{
for ( var m:int = gombas.length - 1; m >= 0; m-- )
{
if (fireballs[i].hitTestObject(gombas[m]))
{
// remove our fireball and gombas graphics
if( fireballs[i].parent != null )
fireballs[i].parent.removeChild( fireballs[i] );
if( gombas[m].parent != null )
gombas[m].parent.removeChild( gombas[i] );
// remove the fireball and gombas from the array; this is assuming
// that once a fireball hits a gomba, they both disappear
gombas.splice( m, 1 );
fireballs.splice( i, 1 );
// break to the outer loop; the fireballs one, as we don't need
// to go any further in the inner one
break outer;
}
}
}
Note the outer label on the fireballs loop; this lets us jump out once we detect a collision between a fireball and a gomba.
If you want a fireball to hit multiple gombas, then just don't remove the graphics or splice the array.

AS3 - Check results from an array and add to a counter

I am trying to make a video quiz and when you click it adds a value of 1 to an array. The array size goes up to [9] and I am trying to read from the array so that if there is a value of 1 in the array between [0] and [9] it will add 1 to the counter.
I have got it working for just the first value in the array so I know it works, but I am not sure about how to make it read from all of the array to check for values of 1.
Heres my code so far:
if (clickTimes[0] == 1)
{
counter2++;
}
Better yet, use a for each...in loop. It's really no different from a regular for loop, but it does provide some synactic sugar.
for each (var i:int in clickTimes)
{
if (i == 1)
{
counter2++;
}
}
For the beauty of it...
counter2 = clickTimes.join('').replace(/0/g, '').length;
It puts all your values in one string, remove the zeros and counts the characters left.
var clickTimes:Array = [1,1,1,0,0,0,1,1,0] // 5 1's and 4 0's
var counter2:int = 0
clickTimes.forEach(function(obj:*){
if (obj == 1){
counter2++;
}
})
trace(counter2) // traces 5
What about using a loop?
for (var i:int = 0; i < clickTimes.length; ++i)
{
if (clickTimes[i] == 1)
counter2++;
}
This would increment counter2, for each element that has a value of 1, in the clickTimes array.
You do not need if. Just the following:
var clickTimes:Array = [1,1,1,0,0,0,1,1,0] // 5 1's and 4 0's
var counter2:int = 0;
for each (var i:int in clickTimes)
{
counter2 += i;
}
trace(counter2); //5

Why is this AS3 code generating an "Error #2006: The supplied index is out of bounds"?

So what I'm trying to do is go through each element of the array "maps" which contains 4 movieclips and look and the children within each of those movieclips to see which are of type "Block". However I'm getting a #2006 error and I'm not sure why, can anyone help please?
function findBlocks()
{
trace("findBlocks()");
for (i=0; maps.length; i++)
{
for (var j=0; maps[i].numChildren; j++)
{
var mc = maps[i].getChildAt(j);
if (mc is Block)
{
blocks.push(mc);
}
}
}
trace("blocks array: " + blocks);
}
Your for loop conditions are incorrect, try this :
for (var i=0; i < maps.length; i++){
for (var j=0; j < maps[i].numChildren; j++){
var mc = maps[i].getChildAt(j);
if (mc is Block){
blocks.push(mc);
}
}
}
You have to remember that arrays and the display list start at 0, so the index of the last element in your lists is length-1, and in the case of a display list numChildren-1
i < maps.length
and
j < maps[i].numChildren
are what solve the problem

Loop through array, set property of each element?

Okay, very simple: there is an array containing 3 objects. Each object has a unique property called "ID" with values of either 1, 2, or 3.
One of the objects gets deleted.
The objective now is to update the ID property of each object corresponding to the new array.length value.
So for example, the object with ID of 2 got deleted. The remaining objects in the array would each have ID values of 1 and 3 respectively.
So the objective is to loop through the array and update the ID properties to 1, and 2 (instead of 1 and 3).
So I guess the question is how to write a loop to update a common property of each element in an array. Thanks.
You can use a for-loop to go through the array, as in walkietokyo's answer, or you can use a method closure:
myArray.forEach ( function ( item:*, i:int, arr:Array) : void { item.ID = i; } );
or a while-loop:
var i:int = -1;
while (++i < myArray.length) myArray[i].ID = i;
for (var i:uint = 1; i <= myArray.length; i++) {
myArray[i].ID = i;
}
General info on loops:
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7fcf.html
var i:uint; // for speed keep out of the loop
var arrayLength = myArray.length // for speed keep out of the loop
for (i = 0; i < arrayLength; i++) {
myArray[i].ID = i;
}