【问题标题】:Sorting a string array with uppercase first including accents使用大写首先对字符串数组进行排序,包括重音符号
【发布时间】:2019-10-08 17:12:29
【问题描述】:

所以我在网上四处寻找 js 中的一些排序功能。这是问题所在。 我们有一个这样的字符串数组:

['único', 'UNICO', 'árbol', 'ARBOL', 'cosas', 'COSAS', 'fútbol', 'FUTBOL']

我们想要这样的东西(大写优先):

['ARBOL', 'COSAS', 'FUTBOL', 'UNICO', 'árbol', 'cosas', 'fútbol', 'único']

或者像这样(小写优先):

['árbol', 'cosas', 'fútbol', 'único', 'ARBOL', 'COSAS', 'FUTBOL', 'UNICO']

问题是:得到这个真的很容易:

['ARBOL', 'COSAS', 'FUTBOL', 'UNICO', 'cosas', 'fútbol', 'árbol','único']

使用.sort(); 函数,但我们不希望最后的重音词,所以我们使用

.sort(function(a, b) {
  return a.localCompare(b);
});

但我们最终得到了这个......

['ARBOL', 'árbol', 'COSAS', 'cosas', 'FUTBOL', 'fútbol', 'UNICO', 'único']

你们知道如何将两者结合起来吗?

【问题讨论】:

  • 查看 MDN sort & localeCompare 文档,localeCompare 中有很多额外的参数
  • @FrV 我怀疑localeCompare 是否可行,请参阅stackoverflow.com/questions/54975581/…
  • 混合大小写的字符串呢?
  • 对不起@MattEllen,我意识到我发布后并不清楚,区别应该是小写和大写的反转。我想我应该尝试编辑原始帖子
  • @AaronC。谢谢!这是有道理的:D

标签: javascript arrays string sorting


【解决方案1】:

您可以简单地扩展排序函数以优先考虑字符串开头的大写字符:

const arr = ['ÁRBOL', 'único', 'UNICO', 'árbol', 'ARBOL', 'cosas', 'COSAS', 'fútbol', 'FUTBOL'];

function startsWithUppercase(str) {
    return str.substr(0, 1).match(/[A-Z\u00C0-\u00DC]/);
}

arr.sort(function(a, b) {
    if (startsWithUppercase(a) && !startsWithUppercase(b)) {
        return -1;
    } else if (startsWithUppercase(b) && !startsWithUppercase(a)) {
        return 1;
    }
    return a.localeCompare(b);
});

console.log(arr);

【讨论】:

  • 这将导致'ÁRBOL' 排在"árbol" 之下。不完全确定 OP 会在那里寻找什么,但我怀疑就是这样
  • 这只是扩展正则表达式以识别带有重音符号的大写字符的问题。我相应地编辑了帖子。
【解决方案2】:

我认为单独使用 localeCompare 是不可能的,请参阅:

How to get localeCompare to behave similarly to .sort(), so that all capital letters come first?:

但是你可以将here描述的方法与sort结合起来:

const arr = ['único', 'UNICO', 'árbol', 'ARBOL', 'cosas', 'COSAS', 'fútbol', 'FUTBOL'];
const norm = str => str.normalize('NFD').replace(/[\u0300-\u036f]/g, "")
arr.sort((a, b) => Number(norm(a) > norm(b)) || -(Number(norm(b) > norm(a))));
console.log(arr);
// ['ARBOL', 'COSAS', FUTBOL', 'UNICO', 'árbol', 'cosas', 'fútbol', 'único']

【讨论】:

    【解决方案3】:

    对数组进行排序,如果:

    1. a 都是大写或者都是小写,通过 localeCompare 排序。
    2. 如果只有a 是大写a 应该是第一个(返回-1)。
    3. 默认(只有b是大写)是b在前(返回1)。

    注意:这里假设所有单词都没有混合大小写字母。

    const arr = ['único', 'UNICO', 'árbol', 'ARBOL', 'cosas', 'COSAS', 'fútbol', 'FUTBOL']
    
    arr.sort((a, b) => {
      const aIsUpperCase = a.toUpperCase() === a;
      const bIsUpperCase = b.toUpperCase() === b;
      
      if(aIsUpperCase === bIsUpperCase) return a.localeCompare(b, 'es');
      
      if(aIsUpperCase) return -1;
      
      return 1;
    })
    
    console.log(arr)

    【讨论】:

      【解决方案4】:

      您可以按大小写拆分它们,将它们排序并重新组合在一起。

      let foo = ['único', 'UNICO', 'árbol', 'ARBOL', 'cosas', 'COSAS', 'fútbol', 'FUTBOL'];
      foo = foo.reduce((a, b) => {
          b.toUpperCase() === b ? a[0].push(b) : a[1].push(b);
          return a;
      }, [[],[]]).flatMap(e => e.sort((a, b) => a.localeCompare(b)));
      
      console.log(foo);

      【讨论】:

        【解决方案5】:

        您可以使用 map 进行排序并将每个字符替换为两个字符,具体取决于字符前面或后面有空格的情况。然后排序和映射一个新数组。

        例子

        未分类

        index  value
        -----  --------------------
           0   'ú   n  i  c  o '
           1   '  U  N  I  C  O'
           2   'á   r  b  o  l '
           3   '  A  R  B  O  L'
           4   ' c  o  s  a  s '
           5   '  C  O  S  A  S'
           6   ' f ú   t  b  o  l '
           7   '  F  U  T  B  O  L'
        

        排序

        index  value
        -----  --------------------
           3   '  A  R  B  O  L'
           5   '  C  O  S  A  S'
           7   '  F  U  T  B  O  L'
           1   '  U  N  I  C  O'
           4   ' c  o  s  a  s '
           6   ' f ú   t  b  o  l '
           2   'á   r  b  o  l '
           0   'ú   n  i  c  o '
        

        var array = ['único', 'UNICO', 'árbol', 'ARBOL', 'cosas', 'COSAS', 'fútbol', 'FUTBOL'],
            result = array
                .map((s, index) => ({ index, value: Array.from(s, c => c === c.toUpperCase()
                    ? '  ' + c
                    : c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'
                        ? ' ' + c + ' '
                        : c + '  '
                ).join('') }))
                .sort((a, b) => a.value.localeCompare(b.value))
                .map(({ index }) => array[index]);
        
        console.log(result);
        .as-console-wrapper { max-height: 100% !important; top: 0; }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多