forked from: Alphanum Algorithm

by yonatan forked from Alphanum Algorithm (diff: 3)
AlphanumComparator.as (AS3 version)

reference: 
http://www.davekoelle.com/alphanum.html
http://www.breaktrycatch.com/alphanumeric-sorting-in-as3/
♥0 | Line 142 | Modified 2012-07-05 04:43:44 | MIT License
play

ActionScript3 source code

/**
 * Copyright yonatan ( http://wonderfl.net/user/yonatan )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/eYkB
 */

// forked from civet's Alphanum Algorithm
/**
 * AlphanumComparator.as (AS3 version)
 * 
 * reference: 
 * http://www.davekoelle.com/alphanum.html
 * http://www.breaktrycatch.com/alphanumeric-sorting-in-as3/
 */
package
{
    import com.bit101.components.List;
    import com.bit101.components.PushButton;
    import com.bit101.components.Style;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.FileReference;
    import flash.net.FileReferenceList;
    
    public class Alphanum extends Sprite
    {
        private var _list:com.bit101.components.List;
        private var _fileRefList:FileReferenceList;
        private var _items:Array;
        
        public function Alphanum()
        {
            Style.embedFonts = false;
            Style.fontSize = 12;
            Style.fontName = "Arial";
            
            _list = new com.bit101.components.List(this, 10, 10);
            _list.setSize(300, 300);
            
            var buttonBrowse:PushButton = new PushButton(this, 10, 320, "OPEN", onBrowse);
            var buttonSort:PushButton = new PushButton(this, 200, 320, "SORT", onSort);
        }
        
        
        private function onBrowse(event:Event):void
        {
            _fileRefList = new FileReferenceList();
            _fileRefList.addEventListener(Event.SELECT, onSelect);
            _fileRefList.browse();
        }
        
        private function onSelect(event:Event):void
        {
            var fileList:Array = _fileRefList.fileList;
            var num:int = fileList.length;
            var items:Array = [];
            for(var i:int=i; i<num; i++) {
                var fileRef:FileReference = fileList[i];
                items[items.length] = {label:fileRef.name, data:fileRef};
            }
            
            _items = items;
            
            _list.items = items;
        }
        
        private function onSort(event:Event):void
        {
            if(!_items || _items.length == 0) return;
            
            var comparator:AlphanumComparator = new AlphanumComparator("label");
            var itemsClone:Array = _items.slice();
            itemsClone.sort(comparator.compareObject);
            _list.items = itemsClone;
        }
    }
}

class AlphanumComparator
{
    private var _fieldName:String;
    
    public function AlphanumComparator(fieldName:String="name")
    {
        _fieldName = fieldName;
    }
    
    private function isDigit(char:String):Boolean
    {
        var code:int = char.charCodeAt(0);
        return code >= 48 && code <= 57;
    }
    
    /** Length of string is passed in for improved efficiency (only need to calculate it once) **/
    private function getChunk(s:String, length:int, marker:int):String
    {
        var chunk:String = "";
        var c:String = s.charAt(marker);
        chunk += c;
        marker++;
        if(isDigit(c)) {
            while(marker < length) {
                c = s.charAt(marker);
                if(!isDigit(c)) break;
                chunk += c;
                marker++;
            }
        }
        else {
            while(marker < length) {
                c = s.charAt(marker);
                if(isDigit(c)) break;
                chunk += c;
                marker++;
            }
        }
        return chunk;
    }
    
    public function compareObject(o1:Object, o2:Object):int
    {
        var s1:String = o1[_fieldName];
        var s2:String = o2[_fieldName];
        
        if(!s1 || !s2) return 0;
        
        return compare(s1, s2);
    }
    
    public function compare(s1:String, s2:String):int
    {
        var marker1:int = 0;
        var marker2:int = 0;
        var length1:int = s1.length;
        var lenght2:int = s2.length;
        
        while(marker1 < length1 && marker2 < lenght2)
        {
            var chunk1:String = getChunk(s1, length1, marker1);
            marker1 += chunk1.length;
            
            var chunk2:String = getChunk(s2, lenght2, marker2);
            marker2 += chunk2.length;
            
            var result:int = 0;
            
            // If both chunks contain numeric characters, sort them numerically
            if(isDigit(chunk1.charAt(0)) && isDigit(chunk2.charAt(0))) {
                
                // Simple chunk comparison by length.
                var len:int = chunk1.length;
                result = len - chunk2.length;
                
                // If equal, the first different number counts
                if(result == 0)
                {
                    for(var i:int = 0; i < len; i++)
                    {
                        result = chunk1.charCodeAt(i) - chunk2.charCodeAt(i);
                        if(result != 0) 
                            return normalize(result);
                    }
                }
            } 
            else {
                //result = chunk1.compareTo(chunk2);
                if(chunk1 < chunk2) { 
                    result = -1; 
                } 
                else if(chunk1 > chunk2) { 
                    result = 1; 
                } 
                else {
                    result = 0; 
                }
            }
            
            if(result != 0) 
                return normalize(result);
        }
        
        //comparison by length
        return normalize(length1 - lenght2);
    }
    
    private function normalize(result:int):int
    {
        return result < 0 ? -1 : (result > 0 ? 1 : 0);
    }
}