Сортировка массива строк в верхнем регистре, включая акценты - PullRequest
7 голосов
/ 22 мая 2019

Так что я бродил по интернету в поисках какой-то функции сортировки в 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']

У вас, ребята, есть идеи, как объединить оба?

Ответы [ 5 ]

4 голосов
/ 22 мая 2019

Вы можете просто расширить функцию сортировки, чтобы установить приоритет символов верхнего регистра в начале строк:

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);
2 голосов
/ 22 мая 2019

Я не верю, что это возможно только с localeCompare, см .:

Как заставить localeCompare вести себя аналогично .sort (), чтобы все заглавные буквы были первыми? :

Но вы можете объединить метод, описанный здесь с 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']
1 голос
/ 22 мая 2019

Сортировать массив, и если:

  1. a в верхнем или нижнем регистре, сортируйте их через localeCompare.
  2. , если только a в верхнем регистре, a должно быть 1-м (возврат -1).
  3. значение по умолчанию (только b в верхнем регистре): b first (возвращаемое значение 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)
0 голосов
/ 22 мая 2019

Вы можете взять сортировку с картой и заменить каждого персонажа двумя символами, в зависимости от случая с пробелом перед или позади символа. Затем отсортируйте и сопоставьте новый массив.

Пример

несортированный

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; }
0 голосов
/ 22 мая 2019

Вы можете разделить их по регистру, отсортировать каждый и собрать обратно.

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...