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

发布于 2024-10-02 06:41:12 字数 490 浏览 4 评论 0原文

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

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

-Montpetit 中 E 上方的重音,以及任何其他带有非英语重音的第一个字母在 Z 之后排序。

Édouard 可以正确排序吗?我无权访问指定的数据。

this is an array of objects that i want to alphabetize:

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"});

now i'll sort my array:

streets.sortOn("name", Array.CASEINSENSITIVE);

//Sorted
Alexandre de Sève
Atwater
Van Horne
Édouard-Montpetit

the accent above the E in Édouard-Montpetit, and any other first letter with a non-english accent is sorted after Z.

any ideas how i can sort this correctly? i do not have access to the named data.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

番薯 2024-10-09 06:41:12

我知道这已经晚了,但是对于任何经历这个答案的人,您可以传递 整理者
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é 

希望这有帮助

I know this is late, but for anyone going through this answer, you could pass a Collator
object to the Array.sort() method. A simple example from the documentation:

 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é 

Hope this helps

凹づ凸ル 2024-10-09 06:41:12

我不认为你可以用 sortOn 来做到这一点,因为没有办法告诉 flash 使用特定的集合来对文本进行排序(至少,我不知道)。

但是,您可以使用 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;
    }
}

I don't think you can do it with sortOn, as there's no way to tell flash to use a particular collaction for sorting text (at least, not that I'm aware of).

However, you could use sort and a custom sort function.

In this sort function, basically you want to strip all accents and do a case insensitive comparation. Replacing diacritics is easy and after that, you can safely use < and > for comparing the strings. A sort function is called by sort with two of the items to be sorted at a time. It should return a negative number if the first passed items sorts first , a possitive number if the second comes first and 0 if they sort equal.

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);

A couple of notes about this. I know this method won't work for Spanish, as you have ñ, which is considered a letter on its own (not a regular n with a funny mark) and comes after n and before o. So, it's not possible to just replace accents and do a < / > compare. I think this is not a problem in French, but I could be wrong (not sure how Ç / ç is considered for sort purposes, for instance). Also, note that I haven't replaced all possible diacritics, so you'd want to add circumflexes (^) and umlauts (¨) to replaceDiacritics as necessary.

Edit

For a table based approach you could try something like the following. Each letter is assigned a number that reflects the sort order. As long as you can assume that any letter will have an absolute sort order (that is, context won't change how this works, which is not the case on some languages), it should give you good results.

Out of laziness, I built the table with a loop and just did what was neccesary to put "Ñ" between "n" and "o". I'm not considering any diacritics for sorting purposes, so they have the same value than their unaccented counterpart. But you could change this table as neccesary. Also, this table probably should be hardcoded for the required locale, but this code is just to give you an idea of how you could do this, not a full implementation (and it's probably not entirely correct from a purist perspective, but I think it could do the job). Also, in case we find a character that is not mapped, I'm falling back to its code point to determine how it sorts.

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文