【问题标题】:How can the Lodash orderBy function be made to work with accented characters?如何使 Lodash orderBy 函数与重音字符一起使用?
【发布时间】:2017-06-24 20:17:54
【问题描述】:

有没有办法让 Lodash 的 orderBy 函数支持重音字符?

如á、é、ñ等。在执行排序时,它们会移到数组的末尾。

【问题讨论】:

    标签: javascript lodash


    【解决方案1】:

    问题

    听起来它不使用localeCompare,而是默认使用<>,它通过UTF-16 代码单元数值进行比较,而不是区域设置排序(排序)。

    控制比较方法

    您可以转换为数组(如果需要),然后将原生 sortlocaleCompare 一起使用。例如,而不是:

    const result = _.orderBy(theArray, ["value"]);
    

    你可以这样做:

    const result = theArray.slice().sort((a, b) => a.value.localeCompare(b.value));
    

    或就地排序:

    theArray.sort((a, b) => a.value.localeCompare(b.value));
    

    localeCompare 对默认语言环境使用默认排序规则。使用Intl.Collator,您可以更好地控制排序规则(如不区分大小写、重音处理、大小写字符的相对位置等)。例如,如果您想要默认语言环境的默认排序规则,但首先使用大写字符:

    const collator = new Intl.Collator(undefined, {caseFirst: "upper"});
    const result = theArray.slice().sort((a, b) => collator.compare(a.value, b.value));
    

    现场示例:

    const theArray = [
        {value: "n"},
        {value: "N"},
        {value: "ñ"},
        {value: "á"},
        {value: "A"},
        {value: "a"},
    ];
    const lodashResult = _.orderBy(theArray, ["value"]);
    const localeCompareResult = theArray.slice().sort((a, b) => a.value.localeCompare(b.value));
    const collator = new Intl.Collator(undefined, {caseFirst: "upper"});
    const collatorResult = theArray.slice().sort((a, b) => collator.compare(a.value, b.value));
    show("unsorted:", theArray);
    show("lodashResult:", lodashResult);
    show("localeCompareResult:", localeCompareResult);
    show("collatorResult:", collatorResult);
    
    function show(label, array) {
        console.log(label, "[");
        for (const element of array) {
            console.log(`    ${JSON.stringify(element)}`);
        }
        console.log("]");
    }
    .as-console-wrapper {
        max-height: 100% !important;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

    稳定与不稳定排序

    当我第一次写这个答案时,_.orderBy 和原生 sort 之间存在细微差别:_.orderBy,如 _.sortBy,总是进行稳定排序,而在原始答案的时间 JavaScript 的原生 sort 不能保证是稳定的。不过,从那时起,JavaScript specification 已被修改为需要稳定的排序 (ES2019)。所以_.orderBy/_.sortBy和原生sort现在都稳定了。

    如果“stable”与“unstable”排序不是熟悉的术语:“stable”排序是指两个在排序目的上被认为是等价的元素,保证相对于彼此保持在相同的位置;在“不稳定”排序中,它们相对于彼此的位置可能会被交换(这是允许的,因为它们对于排序目的是“等效的”)。考虑这个数组:

    const theArray = [
        {value: "x", id: 27},
        {value: "z", id: 14},
        {value: "x", id: 12},
    ];
    

    如果您进行不稳定排序,仅对value 进行升序排序(忽略id 或对象可能具有的任何其他属性),则有两个有效结果:

    // Valid result 1: id = 27 remained in front of id = 12
    [
        {value: "x", id: 27},
        {value: "x", id: 12},
        {value: "z", id: 14},
    ]
    // Valid result 2: id = 27 was moved after id = 12
    [
        {value: "x", id: 12},
        {value: "x", id: 27},
        {value: "z", id: 14},
    ]
    

    但是,对于稳定排序,只有第一个结果是有效的;等价元素相对于彼此的位置保持不变。

    但同样,这种区别不再重要,因为 JavaScript 的 sort 现在也很稳定。

    【讨论】:

    • 请记住,虽然这不是一个稳定的排序,但会受到浏览器内部为 .sort 选择的算法的影响(例如取决于数组的长度)。跨度>
    • @user776686 你到底是什么意思?你能给出更详细的解释吗?喜欢在哪里阅读更多信息的页面(URL)?
    • @stackoverflow - 评论指的是 Lodash 的 _.orderBy/_.sortBy 保证排序稳定,而 JavaScript 的 sort 则没有(允许不稳定)。但是 ES2019 更改了 JavaScript 规范以要求稳定排序,因此不再相关。 (所有主要的 JavaScript 引擎都已经实现了一个稳定的排序 IIRC,因此规范更改实际上并没有改变他们所做的,只是记录了它并要求其他不太流行的实现。)我已经更新了答案以解释这一点并简要解释稳定与不稳定的排序。
    • 干得好@T.J.Crowder 感谢您提供的信息
    【解决方案2】:

    我已经通过比较净化过的元素解决了这个问题。

    theArray.sort(function(a, b) {
        return a.toLowerCase().removeAccents().localeCompare(b.toLowerCase().removeAccents());
    });
    

    removeAccents 函数:

    String.prototype.removeAccents = function () {
    return this
        .replace(/[áàãâä]/gi,"a")
        .replace(/[éè¨ê]/gi,"e")
        .replace(/[íìïî]/gi,"i")
        .replace(/[óòöôõ]/gi,"o")
        .replace(/[úùüû]/gi, "u")
        .replace(/[ç]/gi, "c")
        .replace(/[ñ]/gi, "n")
        .replace(/[^a-zA-Z0-9]/g," ");
    }
    

    【讨论】:

    • 很遗憾,这并不能真正回答问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 2018-09-19
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多