0

Actionscript uses sparse arrays, so I can have an array like this:

var myArray:Array = new Array();
myArray[0] = "foo";
myArray[22] = "bar";

Now myArray.length will give me 23. Is there a way to get the actual number of items in the array without iterating every element?

Robert
  • 6,660
  • 5
  • 39
  • 62

3 Answers3

1

By using for syntax, which will iterate the definded indexes:

public static function definedCount(arr:Array):uint {
    var ctr:uint = 0;
    for(ix:* in arr)
        ctr++;
    return ctr;
}

If you need to frequently check the count of items in a sparse array, you should wrap it an a collection class that independently keeps track of the count of items. Something like:

public class IndexedCollection { 
    private var _arr:Array = [];
    private var _itemCount:uint = 0;

    public function get count():uint {
        return _itemCount;
    }

    public function getItem(index:uint):* { 
        return _arr[index]; 
    }

    public function setItem(index:uint, value:*):void {
        if(_arr[index] === undefined)
            _itemCount++;
        _arr[index] = value; 
    }

    public function delete(index:uint):void { 
        if(_arr[index] === undefined) 
            return;
        delete _arr[index]; 
        _itemCount--;
    }
}
Joshua Honig
  • 12,925
  • 8
  • 53
  • 75
1

If you don't want to iterate through the array, you can filter it:

var myArray:Array = new Array();
myArray[0] = "foo";
myArray[22] = "bar";

var numberOfItems:int = myArray.toString().split(',').filter(isItem).length;

function isItem(item:*, index:int, array:Array):Boolean
{
  return item != "";
}
redhotvengeance
  • 27,446
  • 10
  • 49
  • 54
  • this works assuming your objects are really just strings or you write a toString for your object that has no commas in it's returned value, also I don't get why you would need to use filter, couldn't you just assume all spots that are empty are null instead of an empty string, in which case the Array.toString won't show them anyhow so a split would do it. I like the solution from jmh_gr though due to the possible pitfalls with this one for other object types. – shaunhusain Sep 06 '12 at 21:33
  • 1
    @shaunhusain Yes, there are potential pitfalls. jmh_gr's `IndexedCollection` example is much more bullet-proof. But the OP asked for a way to get the amount of items without iteration - this is certainly an option. And the filter is necessary - try running the `toString().split(',')` without it - it returns 23. – redhotvengeance Sep 06 '12 at 21:50
  • ah okay because the built in toString will still return "" for null i suppose? – shaunhusain Sep 06 '12 at 22:00
  • @shaunhusain Yeah. Tons-o-commas! – redhotvengeance Sep 07 '12 at 00:17
1

Fastest method should be to always use the inbuilt functions.

    function myFilter(item:*, index:int, array:Array):Boolean{
        if(item)
        {
            return true;
        }else{
            return false;
        }
    }

    var myArray:Array = new Array();
    myArray[0] = "foo";
    myArray[22] = "bar";
    trace(myArray.length) // 23
    var myMyNewArray:Array = myArray.filter(myFilter)
    trace(myMyNewArray .length) // 2
The_asMan
  • 6,364
  • 4
  • 23
  • 34