代码之家  ›  专栏  ›  技术社区  ›  Chunky Chunk

非英语数据的ActionScript-Array.sortOn()?

  •  1
  • Chunky Chunk  · 技术社区  · 14 年前

    这是一个按字母顺序排列的对象数组:

    var streets:Array = new Array();
    streets.push({name:"Édouard-Montpetit"});
    streets.push({name:"Alexandre de Sève"});
    streets.push({name:"Van Horne"});
    streets.push({name:"Atwater"});
    

    现在我将对数组进行排序:

    streets.sortOn("name", Array.CASEINSENSITIVE);
    
    //Sorted
    Alexandre de Sève
    Atwater
    Van Horne
    Édouard-Montpetit
    

    E以上的重音在douard Montpetit中,任何其他带有非英语重音的首字母都在Z之后排序。

    有什么办法可以正确分类吗?我没有访问命名数据的权限。

    2 回复  |  直到 14 年前
        1
  •  2
  •   shazinltc    10 年前

    我知道现在很晚了,但如果有人想知道答案,你可以通过 Collator 对象设置为Array.sort()方法。文档中的一个简单示例:

     var words:Array = new  Array("coté", "côte"); 
     var sorter:Collator = new Collator("fr-FR", CollatorMode.SORTING); 
     words.sort(sorter.compare); 
     trace(words);// côte,coté 
    

    希望这有帮助

        2
  •  1
  •   Juan Pablo Califano    14 年前

    我觉得你不能这样做 sortOn ,因为无法告诉flash使用特定的collation对文本进行排序(至少,我不知道)。

    但是,你可以使用 sort 以及自定义排序函数。

    在这个sort函数中,基本上需要去掉所有重音符号并进行不区分大小写的比较。更换变音符号很容易,之后,您可以安全地使用 < > 用于比较字符串。sort函数是通过sort调用的,一次要对其中两个项进行排序。如果第一个传递的项先排序,则返回负数;如果第二个项先排序,则返回负数;如果排序相等,则返回0。

    function sortText(obj1:Object,obj2:Object):int {
        var a:String = replaceDiacritics(obj1.name);
        var b:String = replaceDiacritics(obj2.name);
    
        if(a < b) {
            return -1;
        } else if(b < a) {
            return 1;
        } else {
            return 0;
        }
    }
    
    function replaceDiacritics(str:String):String {
        str = str.toLowerCase();
        str = str.replace(/á/g,"a");
        str = str.replace(/é/g,"e");
        str = str.replace(/í/g,"i");
        str = str.replace(/ó/g,"o");
        str = str.replace(/ú/g,"u");
    
        str = str.replace(/à/g,"a");
        str = str.replace(/è/g,"e");
        str = str.replace(/ì/g,"i");
        str = str.replace(/ò/g,"o");
        str = str.replace(/ù/g,"u");
    
        return str;
    }
    
    streets.sort(sortText);
    

    关于这件事的几点注意事项。我知道这种方法对西班牙语不起作用 ñ ,它被认为是一封单独的信(不是常规的 n 带着一个有趣的标记)然后 n个 在那之前 o . 所以,不可能只替换口音 < / > 比较一下。我认为这在法语中不是问题,但我可能错了(不知道怎么说 Ç / ç 例如,考虑用于排序目的)。另外,请注意,我还没有替换所有可能的变音符号,所以您需要在 replaceDiacritics 必要时。

    编辑

    对于基于表的方法,您可以尝试以下方法。每个字母都分配了一个反映排序顺序的数字。只要你能假设任何一个字母都有一个绝对的排序顺序(也就是说,上下文不会改变它的工作方式,这在某些语言中不是这样的),它就会给你很好的结果。

    出于懒惰,我用一个圈建立了一个表,只做了必要的事情,把“n”和“o”放在中间。我不考虑任何用于排序的变音符号,因此它们的值与未发音的对应项相同。但你可以根据需要换这张桌子。此外,该表可能应该针对所需的区域设置进行硬编码,但这段代码只是让您了解如何做到这一点,而不是一个完整的实现(从纯粹主义者的角度来看,这可能并不完全正确,但我认为它可以做到这一点)。另外,如果我们发现一个未映射的字符,我将返回到它的代码点来确定它的排序方式。

    var sortTable:Object=buildSortTable();

    function buildSortTable():Object {
        var sortTable:Object = {};
        var char:String;
        var offset:int = 0;
        for(var i:int = 1; i < 256; i++) {
            char = String.fromCharCode(i);
            if(char == "Ñ" || char == "ñ") {
                offset--;
                continue;
            }
            sortTable[char] = i + offset;
    
            if(char == "N") {
                sortTable["Ñ"] = sortTable["N"] + 1;
                offset++;
            }
            if(char == "n") {
                sortTable["ñ"] = sortTable["n"] + 1;
                offset++;
            }
    
        }
    
        sortTable["Á"] = sortTable["À"] = sortTable["Ä"] = sortTable["Â"] = sortTable["A"];
        sortTable["É"] = sortTable["È"] = sortTable["Ë"] = sortTable["Ê"] = sortTable["E"];
        sortTable["Í"] = sortTable["Ì"] = sortTable["Ï"] = sortTable["Î"] = sortTable["I"];
        sortTable["Ó"] = sortTable["Ò"] = sortTable["Ö"] = sortTable["Ô"] = sortTable["O"];
        sortTable["Ú"] = sortTable["Ì"] = sortTable["Ü"] = sortTable["Û"] = sortTable["U"];
    
        sortTable["á"] = sortTable["à"] = sortTable["ä"] = sortTable["â"] = sortTable["a"];
        sortTable["é"] = sortTable["è"] = sortTable["ë"] = sortTable["ê"] = sortTable["e"];
        sortTable["í"] = sortTable["ì"] = sortTable["ï"] = sortTable["î"] = sortTable["i"];
        sortTable["ó"] = sortTable["ò"] = sortTable["ö"] = sortTable["ô"] = sortTable["o"];
        sortTable["ú"] = sortTable["ù"] = sortTable["ü"] = sortTable["û"] = sortTable["u"];
    
        return sortTable;
    }
    
    function sortText(obj1:Object,obj2:Object):int {
    
        var a:String = obj1.name.toLowerCase();
        var b:String = obj2.name.toLowerCase();
    
        var len_a:int = a.length;
        var len_b:int = b.length;
    
        var char_a:String;
        var char_b:String;
    
        var val_a:Number;
        var val_b:Number;
    
        for(var i = 0; i < len_a && i < len_b; i++) {
            char_a = a.charAt(i);
            char_b = b.charAt(i);
    
            val_a = sortTable[char_a];
            val_b = sortTable[char_b];
            //  this is just in case we have a letter that we haven't mapped...
            //  let's fall back to using its code point
            if(isNaN(val_a)) {
                val_a = char_a.charCodeAt(0);
            }
            if(isNaN(val_b)) {
                val_b = char_b.charCodeAt(0);
            }
    
            if(val_a < val_b) {
                return -1;
            } else if(val_a > val_b) {
                return 1;
            }
        }
        // both strings are equal so far; so the sorter one (if any) must sort first
        if(len_a < len_b) {
            return -1;
        } else if(len_a > len_b) {
            return 1;
        } else {
            return 0;
        }
    }