AS3: How can you get an Array name from string - arrays

I am trying to copy a 2D array in a temporary array to a permanent one. The problem is that the array it's trying to copy to is dynamic.
I was looking for a way to get string (the new arrays name) to act as the arrays actual name, not the value of any part of the array. I have looked around and this is roughly what I came to:
(this["dynamicArrayName"]) = tempArray;
or
(this[variableWithName]) = tempArray;
(not even sure thats the best way to copy a 2D array).
However, this doesn't work :(. It comes up with so many errors (not syntax).
If there is some way to turn string into an Arrays/Variables name, it would be fantastic to know about.

Just drop the parens in your first example.
function someFunc():void {
var temp:Array = [1,2,3];
this['someArr'] = temp;
}
trace(this['someArr']);
// will output "undefined"
someFunc();
trace(this['someArr']);
// will output "1,2,3"

Related

AS3 SharedObject spooky array entanglement

var so:SharedObject = SharedObject.getLocal("example");
var arr:Array=[1,2,3];
so.data.arr = arr;
so.flush();
trace(so.data.arr); // outputs 1,2,3
arr[2]=5;
trace(so.data.arr); // outputs 1,2,5
As you see, I updated only arr, but so.data.arr got updated as well.
so.data.arr doesn't update if instead of arr[2]=5; i write arr=[1,2,5];
Seems that arr and so.data.arr are linked somehow, but only if I update an element in the arr, not set the whole arr differently.
I discovered this accidentally. Why is it working like that?
Can I count that it works like that every time and use it? Thanks.
Basically speaking arrays are passed by reference, not by value. That means if you assign an array variable to another one you are not creating a new array.
so.data.arr = arr;
means that both so.data.arr and arr point to the same array object. That's why modifications to either one will be reflected by the other. They are pointing at the same thing. But
arr=[1,2,5];
will make arr point to some other array object, remember that [1,2,5] is a short hand version of new Array(1,2,5).
That's why after that line they aren't "linked" any more.

Selecting array to append to with ternary 'if' operator: "Immutable value... only has mutating members"

I have two arrays:
var addedToIgnoreList: [String] = []
var removedFromIgnoreList: [String] = []
I want to append a value to one of these arrays. If I do it like this:
(isUserIgnored ? removedFromIgnoreList : addedToIgnoreList).append("username")
I get Immutable value of type '[String]' only has mutating members named 'append'
It works if I use intermediate variable:
var which = isUserIgnored ? removedFromIgnoreList : addedToIgnoreList
which.append("username")
Is using extra variable the only way?
Update: Extra variable will not work as well, so if statement is the only option. See accepted answer for explanation.
This is all related to arrays being value types, not reference types. That is, the variables don't point to the arrays (unlike, say, an NSArray). They are the arrays, and assigning an array to a new variable makes a fresh copy.
The reason you're getting that error is that this statement:
(isUserIgnored ? removedFromIgnoreList : addedToIgnoreList).append(etc)
makes a temporary copy of one of the two arrays, and the append call is being made on that copy. And that copy will be immutable - this is a good thing, because if it weren't, you might unintentionally mutate it (as you're trying here) only to find that no changes occur - your copy is made, mutated, and then discarded.
Bear in mind that this:
var which = isUserIgnored ? removedFromIgnoreList : addedToIgnoreList
which.append("username")
also makes a copy. So changing which won't change either original array.
The most straightforward way to change the arrays themselves is to use an if statement:
if isUserIgnored {
removedFromIgnoreList.append("username")
}
else {
addedToIgnoreList.append("username")
}
This will make no copies, and instead amend the arrays in-place.
If, on the other hand, you want a fresh array with the value appended, probably the easiest way is to use the + operator:
let newCopy = (isUserIgnored ? removedFromIgnoreList : addedToIgnoreList) + ["username"]
By doing that, assigning first the which variable, you won't be mutating the original array.
What you need to do is to append the element to the variable you want. I don't see any other solution than an if statement.
if isUserIgnored {
removedFromIgnoreList.append("username")
}
else {
addedToIgnoreList.append("username")
}

How do I copy a set of one-dimensional arrays to a two-dimensional array in Processing?

I have these arrays of Strings and I want to load them into an Array of Arrays to process them afterwards.
Specifically, here is my code:
leerHTMLs(String[] urls) {
String[][] htmlsArr;
for (int i = 0; i < urls.length; i++) {
String [i][] htmlsArr = loadStrings(urls[i]);
}
}
I get an error, because "String htmlsArr[i][] = loadStrings(urls[i]);" is claearly not a proper way to initialize an array, right? But how can I move these one-dimensional arrays to my multidimensional array?
I've already tried other things except initializing the multidimensional array with a too-big-to-fail number, but that seems like cheating.
well, you said it yourself! It's an array of arrays! That means when you do
htmlsArr[i]
you will get back the element i from this array of arrays, which is of course, an array! When you do
htmlsArr[i][j]
what you get back is the element j in the array which is the element i in the array of arrays called htmlsArr! The final code should look like this:
void leerHTMLs(String[] urls) {
String[][] htmlsArr;
htmlsArr = new String[urls.length][0];
for (int i = 0; i < urls.length; i++) {
htmlsArr[i] = loadStrings(urls[i]);
}
}
So since loadStrings() returns an array of Strings you tell processing to take the output and put it in the element i of array htmlsArr (which is of course an array).
Technically speaking this is not a proper way to do this sort of thing because saying
htmlsArr = new String[urls.length][0];
means make an array with urls.length number of elements and they should all be arrays with 0 number of elements. But then you overwrite the arrays with other arrays with arrays of arbitrary number of elements, specifically as many as loadStrings may give you.
EDIT:
As per Shane's request in the comments, a more proper way to do it is using list in one of the arrays(external or internal one). That is, of course, in my own humble opinion, because since Processing(Java) allows you to do that you might as well consider it proper. The problem is that when you say something in the likes of:
String [][] arr = new String[3][4];
what you mean is essentially a rectangular array sort of like this:
{{ "a","b","c","e" },
{ "p","y","f","n" },
{ "g","q","r","m" }}
that is, an array with three arrays in, each containing four elements. It is merely for reasons of intuition that I consider this an "improper" way. If your array was like this:
{{ "a","b","c","e","k","h","s" },
{ "p","y" },
{ "g","q","r","m" }}
there is no way to intuitively define it in a new String[3][something] way, although you can always use the stretch in my original answer. (by the way it seems you can also define it with an empty parameter like this: new String[3][])
But since you are going to leave the second dimension of your array undefined, you might as well turn to lists which are more fit for the "unknown number of elements" job. Since it seems you can't create an array of lists you will have to create a list of arrays like this:
ArrayList<String []> a = new ArrayList<String []>();
As you can see there is no definition of numbers of elements here. ArrayLists can take as many as you can add to them, and you can arbitrarily add and remove elements. So what the above code says is that you have a list of String arrays which are not yet defined. Then, in the for loop that reads your urls you can just go:
a.add(loadStrings(urls[i]));
and now there is a new String array element in your ArrayList!

(AS3) Two arrays associated? Change on one changes the other

When I splice an entry from my one array, it splices the same entry from my other array... What is happening?
private static var words:Array = new WordFile().toString().split(/\n/);
private static var wordsTemp:Array;
public static function checkWord (word:String):Boolean
{
var truefalse:Boolean = wordsTemp.indexOf(word+"\r".toLowerCase()) > -1;
trace (words.length)
wordsTemp.splice(wordsTemp.indexOf(word+"\r".toLowerCase()), 1);
trace (words.length)
return truefalse
}
public static function resetArrays :void
{
wordsTemp = words
}
With this code, I call the resetArrays function every time a new game is started. Once in the game, the program will call checkWord with a word being passed to it. If it is found in the word array, it will splice it from the temporary array. However, when I run it, the 2 traces yield 2 different numbers, with the second one being one lower (assuming the word was found in the array). This seems to me to be very strange as I am splicing the temporary array that gets reset, however when tracing the array that is supposed to be unchanged (there is no operations other than the ones I am showing you with it in it) it seems to be changed by a splice in the temporary array...
Any thoughts?
In AS3, all data types except String and Number (and related) are copied by reference
This means that it only copies a reference to the original object when you use myArray1 = myArray2
In more detail, consider the memory at which words is stored is 0x123456
wordsTemp = words will make wordsTemp point to the same memory, i.e. 0x123456
When you do any operation on words, the array at 0x123456 is modified. But this is what wordsTemp refers to. So in reality both are the same object. To make both different, you need to clone the object. In case of an array, you can clone it using any method that modifies the array and returns the new array, e.g. Array.slice
wordsTemp=words.slice(0, words.length); //will do the trick
Or, you could concatenate nothing to the original array and get a duplicate
wordsTemp=words.concat();
Alternatively, if you want to write more lines of code, here's what you can do:
wordsTemp=new Array();
for (var i:int=0; i<words.length; i++) {
wordsTemp.push(words[i]);
}
When you do wordsTemp = words, you don't just assign the array item, but the memory space in the program. You have to copy all item from the first array to the second, but not set it equal has you do.
You can do a loop to copy all item from words to wordsTemp or do something like :
wordsTemp = words.slice(0, words.length);
It will return a copy of the original array without modifying it
Hop that can help
As far as I know, the easiest and "standard" way to clone an array in AS3 is:
var cloneArray:Array = sourceArray.concat();

What does it mean for .slice() to be a "shallow clone"?

ActionScript's Array and Vector classes both have a slice() method. If you don't pass any parameters, the new Array or Vector is a duplicate (shallow clone) of the original Vector.
What does it mean to be a "shallow clone"? Specifically, what is the difference between
Array newArray = oldArray.slice();
Vector.<Foo> newVector = oldVector.slice();
and
Array newArray = oldArray;
Vector.<Foo> newVector = oldVector;
? Also, what if the Vector's base type isn't Foo, but something simple and immutable like int?
Update:
What is the result of the following?
var one:Vector.<String> = new Vector.<String>()
one.push("something");
one.push("something else");
var two:Vector.<String> = one.slice();
one.push("and another thing");
two.push("and the last thing");
trace(one); // something, something else, and another thing
trace(two); // something, something else, and the last thing
Thanks! ♥
In your context, what .slice() does is simply to make a copy of your vector, so that newArray refers to a different object from oldArray, except both seem like identical objects. Likewise goes for newVector and oldVector.
The second snippet:
Array newArray = oldArray;
Vector.<Foo> newVector = oldVector;
actually makes newArray a reference to oldArray. That means both variables refer to the same array. Same for newVector and oldVector — both end up referring to the same vector. Think of it as using a rubber stamp to stamp the same seal twice on different pieces of paper: it's the same seal, just represented on two pieces of paper.
On a side note, the term shallow copy differs from deep copy in that shallow is a copy of only the object while deep is a copy of the object and all its properties.
Also, what if the Vector's base type isn't Foo, but something simple and immutable like int?
It's the same, because your variables refer to the Vector objects and not their ints.
What is the result of the following?
Your output is correct:
something, something else, and another thing
something, something else, and the last thing
two = one.slice(), without any arguments, makes a new copy of one with all its current contents and assigns it to two. When you push each third item to one and two, you're appending to distinct Vector objects.

Resources