PDA

View Full Version : filtering array by keywords


fdqepd
03-20-2008, 11:06 PM
Hi

I've been fighting for a while and cant seem to get it working

if anyone could give me a hand with the looping structure i would appreciate it.

blueprint
projectsArray:Array; - all the projects from the xml
pKeywords:Array; - every project has 1 or more keywords
activeKeywords:Array; - the keywords that ar currently selected
filteredProjects:Array; - the projects that match 1 or many activeKeywords

good luck to myslef!

lordofduct
03-20-2008, 11:15 PM
Here's the basic set up of the filter function:

myFilteredCloneArray = myArray.filter(myFilterFunction);

function myFilterFunction(obj:*, index:int, arr:Array):Boolean {
return (obj.myPropertyToCheck == //thing we want to check)
}

where are these keywords held? If it is a property, and the index of the keys matches the index of the object you are checking, then you can stick this in your filter's function:

var i:int = arr.indexOf(obj);
return (obj.myProperty == myKeyArray[i]);

now if the keys are inspecific to a single object... then use a some function inside of the filter function. The some function can check an array to see if atleast 1 of the values equals the parameter you choose.

kinda like this:


var myArray:Array = new Array("1", "2", "3", "4");
var myKeyArray:Array = new Array("2", "3");

var myFilteredCloneArray:Array = myArray.filter(myFilterFunction);

function myFilterFunction(obj:*, index:int, arr:Array):Boolean {
return myKeyArray.some(someFunction);

function someFunction(key:*, i:int, a:Array):Boolean {
return (key == obj);
}
}

trace(myFilteredCloneArray.toString()); //trace "2, 3"


remember the some and filter methods require functions that return Boolean's. It just sees if it is true or not.

With the filter, if true is returned, it pushes that object for that index into a new array and returns said array.
With the some mehtod, if true is returned for ANY of the objects in the array, it returns true for all. If none return true, it stays false. Of course this method only returns a Bool in the end.

sgartner
03-21-2008, 01:38 AM
Hi

I've been fighting for a while and cant seem to get it working

if anyone could give me a hand with the looping structure i would appreciate it.

blueprint
projectsArray:Array; - all the projects from the xml
pKeywords:Array; - every project has 1 or more keywords
activeKeywords:Array; - the keywords that ar currently selected
filteredProjects:Array; - the projects that match 1 or many activeKeywords

good luck to myslef!

You mentioned XML in there so if your original data is XML, moving directly to arrays and then trying to filter the data may be wasteful as there might be an easy way to do it with E4X. If you provide your original XML data and a description of what you need to pull out of it you might get a much more elegant solution.

fdqepd
03-21-2008, 02:52 PM
lordofduct, thanks for the tips, but i still cant get it right, heres some more info since sgartner requested it.

This is my keywords xml.
its organized in groups cause it shows up in groups later

<?xml version="1.0" encoding="utf-8"?>
<ROOT>
<KGROUP>
<KEYWORD>A_keyword</KEYWORD>
</KGROUP>
<KGROUP>
<KEYWORD>B_keyword</KEYWORD>
</KGROUP>
</ROOT>

then, ive got my projects xml with this structure

<?xml version="1.0" encoding="utf-8"?>
<ROOT title='projects'>
<PROJECT keywords='A_keyword'>
<NAME>projectName</NAME>
<DATE>aDate</DATE>
<CLIENT>aClient</CLIENT>
</PROJECT>
<PROJECT keywords='A_keyword, B_keyword'>
<NAME>projectName</NAME>
<DATE>aDate</DATE>
<CLIENT>aClient</CLIENT>
</PROJECT>
</ROOT>


and then i populate 2 arrays


keywords = ({name:"A_keyword", isActive:false}, {name:"B_keyword", isActive:false})

allProjects = ({pName:"projectName", pKeywords:new Array("A_keyword")}, {pName:"projectName", pKeywords:new Array("A_keyword", "B_keyword")})


now i want to create a new array to hold filtered projects according to active keywords (wich i set from a checkbox list)


filteredProjects = allProjects.filter(putIfNotThere);

private function putIfNotThere(obj:*, index:int, arr:Array):Boolean {
for( var i:int = 0; i<obj.pKeywords.length; ++i){
return (obj.pKeywords[i] == keywords.some(isActive));
break;
}

}

private function isActive(element:*, index:int, arr:Array):Boolean {
return (element.isActive == true);
}


i cant seem to use the for loop inside the filter function. output says
1170: Function does not return a value.

thanks for the quick feedback guys!
hope you can help me sort this out

cheers

wvxvw
03-21-2008, 03:10 PM
var xml:XML = <ROOT title='projects'>
<PROJECT keywords='A_keyword'>
<NAME>projectName</NAME>
<DATE>aDate</DATE>
<CLIENT>aClient</CLIENT>
</PROJECT>
<PROJECT keywords='A_keyword, B_keyword'>
<NAME>projectName</NAME>
<DATE>aDate</DATE>
<CLIENT>aClient</CLIENT>
</PROJECT>
</ROOT>;
var xmll1:XMLList = xml.descendants().(/[A_keyword|B_keyword]/.test(attribute('keywords')));
var xmll2:XMLList = xml.descendants().(/B_keyword/.test(attribute('keywords')));
trace(xmll1.toXMLString());
trace('================================');
trace(xmll2.toXMLString());
Will this help?

fdqepd
03-21-2008, 03:36 PM
works like a charm! ill have to fix some other functions to fit the xmlList, but this is by far much more simple than what i had in mind!
hurra as3! and xml parsing kick ass fucntions

thanks guys!

var xml:XML = <ROOT title='projects'>
<PROJECT keywords='A_keyword'>
<NAME>projectName</NAME>
<DATE>aDate</DATE>
<CLIENT>aClient</CLIENT>
</PROJECT>
<PROJECT keywords='A_keyword, B_keyword'>
<NAME>projectName</NAME>
<DATE>aDate</DATE>
<CLIENT>aClient</CLIENT>
</PROJECT>
</ROOT>;
var xmll1:XMLList = xml.descendants().(/[A_keyword|B_keyword]/.test(attribute('keywords')));
var xmll2:XMLList = xml.descendants().(/B_keyword/.test(attribute('keywords')));
trace(xmll1.toXMLString());
trace('================================');
trace(xmll2.toXMLString());
Will this help?

fdqepd
03-21-2008, 06:07 PM
var xmll2:XMLList = xml.descendants().(/B_keyword/.test(attribute('keywords')));

can i replace /B_keyword/ with an array or var?? How?



works like a charm! ill have to fix some other functions to fit the xmlList, but this is by far much more simple than what i had in mind!
hurra as3! and xml parsing kick ass fucntions

thanks guys!

fdqepd
03-21-2008, 07:41 PM
hello, great help!

how could i replace the RegExp with an array?
is that possible?

fdqepd
03-21-2008, 08:47 PM
figured it out, im posting for anyone who needs something like this

Thanks guys
couldnt have done it without your help (not this easy at least)


var keywordsString:String = activeKeywords.toString();
var keyRegExp:RegExp = new RegExp(keywordsString.replace(/,/, "|"));
filteredProjects = projectsData.children().(keyRegExp.test(attribute( 'keywords')));


now the new list is filtered accoording to dynamically set keywords.
bye