Nick
Nick

Reputation: 1269

Iterate through array of Objects

I have an created an associative array of MovieClips, but when I try to iterate through them, the for loop never gets entered (nothing gets outputted). It's like as-if the Array is empty.

Any ideas?

var navItems:Array = new Array();
navItems["home"] = item_home;
navItems["featuredfilms"] = item_featuredfilms;
navItems["nowshowing"] = item_nowshowing;
navItems["trailers"] = item_trailers;
navItems["comingsoon"] = item_comingsoon;
navItems["yourtickets"] = item_yourtickets;

function registerNavigationEvents():void {
    for (var item in navItems) {
        trace("Hello");
        //item.addEventListener(MouseEvent.MOUSE_OVER, handleNavToggle);
    }
}

Dictionary:

var navItems:Dictionary = new Dictionary();
navItems["featuredfilms"] = item_featuredfilms;
navItems["nowshowing"] = item_nowshowing;
navItems["trailers"] = item_trailers;
navItems["comingsoon"] = item_comingsoon;
navItems["yourtickets"] = item_yourtickets;

function registerNavigationEvents():void {
    for(var key:String in navItems) {
        trace("Hello");
        //item.addEventListener(MouseEvent.MOUSE_OVER, handleNavToggle);
    }
}

Upvotes: 1

Views: 2317

Answers (4)

user797257
user797257

Reputation:

First of all, to get the terminology straightened: no, you didn't create an associative array. AS3 doesn't provide an implementation for associative arrays. Associative array is a sequence of key-value pairs (sequence is different from set in that it defines order of it's elements). There is no requirement for sequence that pairs be unique (arrays are a particular case of a sequence, and it is common for arrays to contain the same element multiple times). Associative array may as well contain same element more then once. A typical example is a get request that contains something like this: example.org/?foo=bar&foo=bar.

Now, what you created can be thought of as a set of string keys which maps to a set of some other objects, with a requirement that every string be unique. Commonly, in other languages, this construct is called a map. However, map implies certain customary implementation. Map would usually have special methods for memory allocation, hashing the keys for faster access, calculating the number of items contained in the map etc. It is not uncommon for maps to be implemented as trees.

So, finally, what happened is that you created an instance of dynamic class, and added some properties to it. To complicate things even further :) properties of a class are not strings! They are QName's (qualified names). I.e. pairs of namespace and string key. The mechanism that backs up these properties is very similar to map, however, you aren't given all the controls to use it as an actual map.

I've described all this in order to convince you that a more straight-forward way from the "computer" point of view would be to use either Array:

var navItems:Array = [item_featuredfilms, item_nowshowing, 
    item_trailers, item_comingsoon, item_yourtickets];

in which case you can later refer to each element navItems[x], x being the offset into array. You could use for-in and for-each loops on this array, iterating over keys and values respectively.

Alternatively, you could use Dictionary, however, not in the way you originally did:

var navItems:Dictionary = new Dictionary();
navItems[item_featuredfilms] = "featuredfilms";
. . .
navItems[item_yourtickets] = "yourtickets";

Again, later you could iterate over keys in for-in (keys are the objects, not the strings), and over values by using for-each (the values in this example are strings).

Which one to choose is up to you. The factors you would need to consider are these: Array.indexOf() is an O(n) operation because it needs, in the worst case, to look into each element of array to find the element index you are looking for, while dictionary[key] is an O(1) operation. However, if you need to find the object by it's key, then the exact opposite is true: array[index] is an O(1) operation, but you would need to loop through the dictionary to find the key you need.

private function iterateTest():void
{
    var dictionary:Dictionary = new Dictionary();
    var array:Array = [];

    // Array is a complex type, thus, it will be used 
    // by reference, and it is OK to use it as 
    // dictionary keys
    var one:Array = ["one"];
    var two:Array = ["two"];
    var three:Array = ["three"];

    var key:Object;
    var value:Object;

    dictionary[one] = 1;
    dictionary[two] = 2;
    dictionary[three] = 3;

    // note, you could do this in plenty of ways, 
    // for example: array.push(one, two, three)
    // or array = [one, two, three]
    // I did it like this for consistency of this example only.
    array[1] = one;
    array[2] = two;
    array[3] = three;

    for each (value in dictionary) trace(value);
    for (key in dictionary) trace(key, dictionary[key]);

    for each (value in array) trace(value);
    for (key in array) trace(key, array[key]);

    // Output:
    // 1
    // 2
    // 3
    // one 1
    // two 2
    // three 3
    // one
    // two
    // three
    // 1 one
    // 2 two
    // 3 three
}

wherever in the output you see a digit, the actual number was used in code, whenever in the output you see a cardinal, a complex object was used.

Upvotes: 0

weltraumpirat
weltraumpirat

Reputation: 22604

First of all, it seems to me your problem is that you never actually call registerNavigationEvents()...

Anyway, if you want to create an associative array, you have to use either an Object or a Dictionary. Array has a numerical index by default.

You can iterate over the keys in both associative types using for...in, they differ mostly in that Dictionary accepts any object as key, while Object accepts only strings:

var obj:Object = {};
for (var key : String in obj) {
    var value : Object = obj[key];
}

var dict:Dictionary = new Dictionary();
for (var key : Object in dict) {
    var value : Object = dict[key];
}

There are some more differences, but you can read about that here or in the AS3 doc yourself.

You can assign values using the bracket operator, just like you did in your code, or use dot syntax:

obj.key = value;   // same as obj["key"] = value;
dict.key = value;  // same as dict["key"] = value;

though obviously, this would imply that all your dictionary keys would be strings, as well. Note that using dot syntax means actually using your dictionary exactly like an Object; the speed boost you get from Dictionary is achieved by using object pointers as keys - which can't be done with strings and numbers.

You can iterate array values using for each...in:

var array:Array = [];
for each (var item:Object in array) { 
   // item can also have strong typing, it will be cast automatically
}

This also works for dictionaries and objects. However, you cannot be sure about the order in which the values are returned!

Upvotes: 0

Foggzie
Foggzie

Reputation: 9821

Use the push() function to add to your array:

navItems.push(item_home);
//...
navItems.push(item_yourtickets);

An array uses a numeric index to retrieve data. If you would like to have an associative container that uses string for retrieval, look into the Dictionary class: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/Dictionary.html

Upvotes: 0

Matt MacLean
Matt MacLean

Reputation: 19648

Try this:

for ( var key:String in navItems ) {
    var mc:MovieClip = navItems[key] as MovieClip;
    // do stuff here
}

or:

for each ( var item:MovieClip in navItems ) {
    // do stuff here
}

Upvotes: 2

Related Questions