E4X: sort XMLList by month?
I'm trying to sort the XML list by month, the actual tags have more attributes than the month, but for brevity I won't include them:
<var month="OCT"/>
<var month="NOV"/>
<var month="JAN"/>
<var month="MAR"/>
<var month="SEP"/>
<var month="JUL"/>
<var month="APR"/>
<var month="AUG"/>
<var month="DEC"/>
<var month="FEB"/>
<var month="MAY"/>
<var month="JUN"/>
How can I sort this list in order by month? ... I don't mean alphabetically, I mean JAN, FEB, MAR, etc.
Thanks!
a source to share
I came up with this solution this morning:
function sortXMLListByMonth(xmlList:XMLList):XMLList
{
var months:Array = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'];
var xml:XML = new XML(<temp></temp>);
for(var i:uint = 0; i<months.length; i++)
{
var tmp:XMLList = xmlList.(@month == months[i]);
xml.appendChild(tmp);
}
return xml.children();
}
It doesn't actually sort the XMLList, but returns a sorted copy.
a source to share
I don't quite understand how you are given the data, but if you want to actually sort the XML, I assume you just need to write a custom sort function.
If you have objects or can analyze them into objects, you can use a custom compare function. Here is the function I used to sort case-insensitively in the mobile operator array collection. I also used it to skip sorting the first item in the collection of an array - CARRIER DEFAULT:
private function x(event:ResultEvent):void{
for(i=0; i<event.result.carriers.carrier.length; i++){
_mobile_carriers.addItem({label:event.result.carriers.carrier[i].name, data:event.result.carriers.carrier[i].id});
}
var sort:Sort = new Sort();
sort.fields = [new SortField("label")];
sort.compareFunction = caseInsensitiveSort;
_mobile_carriers.sort = sort;
_mobile_carriers.addItemAt({label:"Mobile Carrier", data:0},0);
_mobile_carriers.refresh();
}
private function caseInsensitiveSort(obj1:Object, obj2:Object, fields:Array):int{
if(obj1.label == CARRIER_DEFAULT) return -1;
if(obj2.label == CARRIER_DEFAULT) return 1;
return (obj1.label.toLowerCase() < obj2.label.toLowerCase()) ? -1 : 1;
}
If you need to sort the strings, specify the months and then you can just compare them as they will display to whole numbers. There might be a better way to do this, but as a quick solution, I could collect the hash:
month_hash=
"JAN" => 1
"FEB" => 2
"MAR" => 3
...
Here is some pseudocode for comparison that can be used in custom comparison code, or as a sort function for Sort ()
function compare(s1,s2){
var m1 = ""
var m2 = ""
if (s1 =~ /month="([A-Z]+)"/) m1 = $1;
if (s2 =~ /month="([A-Z]+)"/) m2 = $1;
if(m1 == "" or m2 == ""){
throw exception;
}else{
if(month_hash(m1) > month_hash(m2)){
// string 1 month comes after string 2 month
// return whatever will indicate that
return 1;
}else if(month_hash(m1) < month_hash(m2)){
// string 1 month comes before string 2 month
// return whatever will indicate that
return -1;
}else{
//same month
//return 0
}
}
}
No time to post the exact code, but hope this helps!
a source to share