AS3: Array.filter R0xr!

by troy on December 16, 2007

Array in AS3 has some nifty features that make managing and manipulating active data much easier. Thanks to Brandon Hall's nooks and crannies presentation at LA Flash for getting me to look. Here's an example of using Array.filter

Here's the minimum filter that doesn't do anything. I default the last parameters as often filters are useful outside of iterating over arrays, but the filter method nicely tells the filter where it is via the 'index' and a reference back to the Array.

	public class Filter {
		public function passesFilter(item:*,  index:int= 0, array:Array = null):Boolean{
			var passes:Boolean = true;
			return passes;
		}
	}

It's used like

      var results:Array = arrayToFilter.filter(someFilterFunction);

Inside com.troyworks.data.filters. I've created a family of filters, in particular RangeFilter that allows inclusive and exclusive of a given range. Here's what a 3-8 filter looks like:


3-8 filter.. 0123456789012345678
* inclusive ---[PASS]----------
noninclusive ---]PASS[----------

     var arrayToFilter:Array = [0,1,2,3,4,5,6,7,8,9];
     var filter:NumberRangeBooleanFilter   = new NumberRangeBooleanFilter(3, 5); //anything from 3-5
      var results:Array = arrayToFilter.filter(NumberRangeBooleanFilter.filter); //returns 3,4,5

The real power of filters is they can be stacked. Here's an example of using a color filter, that looks for color values in the midgray band, but adds an additional filter so that values to close to gray are thrown out.

//find values from 0x555555 to 0xBBBBBB non-inclusive on both sides
	var midsFilter:ColorStatisticFilter = new ColorStatisticFilter( ColorUtil.GRAY5, ColorUtil.GRAYB, false, false);
	midsFilter.distanceFromShadeFilter = new NumberRangeBooleanFilter(36, 255);
     // second param needs to be null as this filter is a function closure instead of an anonymous function.
      var midColors:Array = indexedColors.filter(midsFilter.passesFilter,null);

{ 6 comments… read them below or add one }

leo beldia May 11, 2009 at 5:34 am

Hello :)
can I ask for some more sample? I had a hard time looking for a solution on how this DataProvider.getItemIndex() work on my project. Returns -1 even if I have exactly the same Object. I’ve seen some topics here: http://www.actionscript.org/forums/showthread.php3?t=149781 but said to use filter() so I end up here in your page. I could not understand the help guide of adobe live doc.

Please help.

Thank you.

troy May 11, 2009 at 6:39 pm

Hi Leo, I’ve added a sample I’m not sure exactly you need, or why DataProvider.getItemIndex isn’t working for you. Are you absolutely you’re storing the same reference in the array as you’re searching for.

There’s nothing magic about filters. You can just as easily do a loop (this is probably wrong but close)

var i:int =0;
for(i =0; i < dataprovider.length(); i++){
   var item:Object = dataprovider.getItemAt(i);
   if(item == theItemYouWant){
       trace("found item at " + i);
       break;  
    }
}

but I’ve updated the post with a bit more information on how filter. Check out the PDF I linked to.

leo May 11, 2009 at 9:23 pm

Hi Troy,
I tried your suggestion above. Here the code:
*note: dpItemList is our dataprovider here.

var oItemList:Object = new Object();

oItemList = Object({Itemcode:currItemcode, ModelNo:currModelNo, Pic:currPic, Qty:currQty, Branch:currBranch});

for(i=0; i<dpItemList.length; i++){
if(oItemList == dpItemList.getItemAt(i)) lblFeedback.text = “found at ” + i.toString();
}

Unfortunately, it doesn’t work. I tried this other option anyway and it works,

var branch:String;

branch=”KWH”;

for(i=0; i<dpItemList.length; i++){
if(branch == dpItemList.getItemAt(i).Branch.toString()) lblFeedback.text = “found at ” + i.toString();
}

if i’ll do: dpItemList.getItemAt(i).Branch.toString(), dataprovider will return a string and object if this one: dpItemList.getItemAt(i). Only that, i really don’t know if my object oItemList matches with the value returned by this dpItemList.getItemAt(i) that’s why I did not get any result. I’ll temporarily use the 2nd option while figuring how this thing works :-) and maybe learn how to embed codes here. hahaha :-) Sorry i don’t know how to use this comment box.

anyway, thank you very much troy.

leo May 11, 2009 at 9:40 pm

By the way, about getItemIndex(), here’s my sample code:

var oItemList:Object = new Object();

oItemList = Object({Itemcode:currItemcode, ModelNo:currModelNo, Pic:currPic, Qty:currQty, Branch:currBranch});

lblFeedback.text = dpItemList.getItemIndex(oItemList).toString();

This one returns -1 value. Means that nothing matches with my object inside dataprovider. I already checked the values one by one to make sure that all variables has values but still to no avail. I don’t know if I declared them correctly :-)

troy May 11, 2009 at 9:51 pm

Ah, do you know the difference between pass by reference and pass by value? That’s the reason why you’re second one works.

when getting the index of it looks for identity/reference not having the value of.

var a1:String = “A”;
var a2:String = “A”;

a1 === a2 // false they are different instances. (what you asked for in #1)
a1 == a2 //true they have the same value (what you did in #2)

Do a search on the web for pass by value
http://www.cs.princeton.edu/~lworthin/126/precepts/pass_val_ref.html

An alternate way is to search by some unique ID, e.g. your itemcode or branch. If Branch truly is a string then you shouldn’t have to call it’s toString() method.

leo May 13, 2009 at 12:01 am

This confused me because ‘===’ is a strict equality in PHP. Means that; it will check if both variables are equal and of the same datatype. I guess I need to do more some research about this. hehe :) anyway, thank you very much troy. This topic enlightens me why dataprovider returns -1 in using getItemIndex() function.

Leave a Comment

Previous post:

Next post: