Как сравнить строки Unicode в Javascript?

Когда я написал на JavaScript "Ł" > "Z", он возвращает true. В порядке Unicode это должно быть, конечно, false. Как это исправить? Мой сайт использует UTF-8.


person Tomasz Wysocki    schedule 02.09.2010    source источник
comment
Что именно вы пытаетесь сделать? Возможно, есть обходные пути.   -  person Pekka    schedule 02.09.2010
comment
Я пытаюсь отсортировать таблицу на основе имен пользователей, и у меня есть такие буквы, как Ł.   -  person Tomasz Wysocki    schedule 02.09.2010
comment
Другими словами, оно должно идти сразу после L? т.е. ..J,K,L,Ł,M,N,O..?   -  person BalusC    schedule 03.09.2010
comment
да. Вы можете найти полную последовательность для польского языка здесь: en.wikipedia.org/wiki/Polish_alphabet .   -  person Tomasz Wysocki    schedule 03.09.2010
comment
Термин, который вы ищете, - это сопоставление, и это, как известно, сложно. Не существует такой вещи, как порядок Unicode; Unicode явно признает тот факт, что разные локали имеют разный порядок. См. unicode.org/reports/tr10 – не предоставляет следующие функции: ... Лингвистические применимость   -  person MSalters    schedule 03.09.2010
comment
Кроме того, "Ła" > "Le" ?   -  person MSalters    schedule 03.09.2010
comment
Я изменил «UTF-8» в заголовке вопроса на «Unicode», так как проблема не зависит от конкретной кодировки передачи. (Кроме того, внутри JavaScript используется UTF-16, а не UTF-8, даже если кодировка HTML-документа — UTF-8.)   -  person Jukka K. Korpela    schedule 12.05.2014
comment
Ну, есть порядок Unicode, но он не будет соответствовать польскому порядку.   -  person hippietrail    schedule 03.04.2015


Ответы (6)


Вы можете использовать Intl.Collator или String.prototype.localeCompare, представленный API интернационализации ECMAScript:

"Ł".localeCompare("Z", "pl");              // -1
new Intl.Collator("pl").compare("Ł","Z");  // -1

-1 означает, что Ł предшествует Z, как вы и хотели.

Обратите внимание, что это работает только в последних браузерах.

person Oriol    schedule 12.05.2014
comment
Если вам нужно отсортировать список многоязычных слов. Например список имен людей из разных стран. Это не сработает, не так ли? - person Mic; 22.10.2018

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

var alpha = function(alphabet, dir, caseSensitive){
  return function(a, b){
    var pos = 0,
      min = Math.min(a.length, b.length);
    dir = dir || 1;
    caseSensitive = caseSensitive || false;
    if(!caseSensitive){
      a = a.toLowerCase();
      b = b.toLowerCase();
    }
    while(a.charAt(pos) === b.charAt(pos) && pos < min){ pos++; }
    return alphabet.indexOf(a.charAt(pos)) > alphabet.indexOf(b.charAt(pos)) ?
      dir:-dir;
  };
};

Чтобы использовать его в массиве строк a:

a.sort(
  alpha('ABCDEFGHIJKLMNOPQRSTUVWXYZaàâäbcçdeéèêëfghiïîjklmnñoôöpqrstuûüvwxyÿz')
);

Добавьте 1 или -1 в качестве второго параметра alpha() для сортировки по возрастанию или убыванию.
Добавьте true в качестве третьего параметра для сортировки с учетом регистра.

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

person Mic    schedule 02.09.2010
comment
Если вы используете этот код, см. также: stackoverflow.com/questions/3630645/ - person Tomasz Wysocki; 04.09.2010
comment
Эй! Вам действительно нужно пройти через все это? Как насчет того, чтобы забыть сначала поместить его в форму нормализации D? Действительно ли PHP не имеет ничего эквивалентного Unicode::Collate Perl и модули Unicode::Collate::Locale? ДЕЙСТВИТЕЛЬНО? Кажется полным безумием пытаться переделать все это самостоятельно! - person tchrist; 19.11.2010
comment
@tchrist, здесь не PHP, а javascript, и он такой, какой он есть. - person Mic; 20.11.2010

Вы можете создать свою собственную функцию сортировки, используя localeCompare() это, по крайней мере, в соответствии с Статья MDC по теме - должно правильно сортировать вещи.

Если это не сработает, вот интересный вопрос SO где OP использует замену строк для создания механизма сортировки методом «грубой силы».

Также в этом вопросе OP показывает, как построить >пользовательская функция textExtract для подключаемого модуля jQuery tablesorter, которая выполняет сортировку с учетом локали - возможно, на нее тоже стоит обратить внимание.

Редактировать: В качестве совершенно невероятной идеи - я понятия не имею, возможно ли это вообще, особенно из-за проблем с производительностью - если вы все равно работаете с PHP/mySQL на сервере, я хотел бы упомянуть возможность отправки запроса Ajax в экземпляр mySQL для его сортировки там. mySQL отлично подходит для сортировки данных с учетом локали, потому что вы можете принудительно выполнить операции сортировки в определенном сопоставлении, используя, например, ORDER BY xyz COLLATE utf8_polish_ci, COLLATE utf8_german_ci.... эти сопоставления позаботятся обо всех проблемах сортировки сразу.

person Pekka    schedule 02.09.2010
comment
Спасибо. для ссылок. Немного обидно, что JavaScript не поддерживает его в ядре, но тем не менее это рабочее решение. - person Tomasz Wysocki; 03.09.2010
comment
Будьте осторожны с localeCompare() в IE6: blog.schmichael.com/2008/ 14 июня/сбой сортировки javascript - person BalusC; 03.09.2010
comment
@BalusC в комментариях к этой статье утверждается, что на самом деле это вина Wine, а не IE6. Не могу найти ничего другого по этой проблеме, чтобы подтвердить или опровергнуть это, и мне слишком лень создавать тестовый пример прямо сейчас ... @Tomasz, если вы пойдете по этому пути, было бы интересно услышать, хорошо ли все работает в IE6. - person Pekka; 03.09.2010
comment
О, я не видел комментарий раньше. В любом случае, чтобы избежать непредвиденных несоответствий браузера (у меня все еще нет четкого представления о localeCompare()), я бы реализовал собственный, как это сделал Томалак в вашей связанной теме. - person BalusC; 03.09.2010
comment
@BalusC Я согласен, что это, вероятно, лучший и самый надежный способ. - person Pekka; 03.09.2010
comment
Из подходов с жестким кодом мне больше всего нравится подход Мика. Это более явно, чем замена-сравнение. localeCompare было бы здорово, но не работает для всех браузеров/конфигураций (например, не работает для моего Google Chrome, но отлично работает на Fifrefox (тот же компьютер)). - person Tomasz Wysocki; 03.09.2010

Код Mic улучшен для неупомянутых символов:

var alpha = function(alphabet, dir, caseSensitive){
  dir = dir || 1;
  function compareLetters(a, b) {
    var ia = alphabet.indexOf(a);
    var ib = alphabet.indexOf(b);
    if(ia === -1 || ib === -1) {
      if(ib !== -1)
        return a > 'a';
      if(ia !== -1)
        return 'a' > b;
      return a > b;
    }
    return ia > ib;
  }
  return function(a, b){
    var pos = 0;
    var min = Math.min(a.length, b.length);
    caseSensitive = caseSensitive || false;
    if(!caseSensitive){
      a = a.toLowerCase();
      b = b.toLowerCase();
    }
    while(a.charAt(pos) === b.charAt(pos) && pos < min){ pos++; }
    return compareLetters(a.charAt(pos), b.charAt(pos)) ? dir:-dir;
  };
};

function assert(bCondition, sErrorMessage) {
      if (!bCondition) {
          throw new Error(sErrorMessage);
      }
}

assert(alpha("bac")("a", "b") === 1, "b is first than a");
assert(alpha("abc")("ac", "a") === 1, "shorter string is first than longer string");
assert(alpha("abc")("1abc", "0abc") === 1, "non-mentioned chars are compared as normal");
assert(alpha("abc")("0abc", "1abc") === -1, "non-mentioned chars are compared as normal [2]");
assert(alpha("abc")("0abc", "bbc") === -1, "non-mentioned chars are compared with mentioned chars in special way");
assert(alpha("abc")("zabc", "abc") === 1, "non-mentioned chars are compared with mentioned chars in special way [2]");
person Tomasz Wysocki    schedule 03.09.2010

Вы должны сохранить две строки сортировки. Один для первичного порядка, где немецкий ä=a (первичный a->a) и французский é=e (первичный ключ сортировки e->e), и один для вторичного порядка, где ä идет после a (перевод a->azzzz во вторичном key) или é следует после e (дополнительный ключ e->ezzzz). Особенно в чешском языке некоторые буквы являются вариациями буквы (áéí…), тогда как другие стоят в полном порядке в списке (ABCČD…GHChI…RŘSŠT…). Плюс проблема считать орграфы одной буквой (основной ch->hzzzz). Нет тривиальной проблемы, и в JS должно быть решение.

person xandru    schedule 23.01.2019
comment
улучшите свой ответ, используя параметры формата по умолчанию - person Harsh Patel; 23.01.2019
comment
Решение: myArray.sort(new Intl.Collator('pl').compare); - person xandru; 23.01.2019

Забавно, я должен подумать об этой проблеме и закончил поиск здесь, потому что мне пришло в голову, что я могу использовать свой собственный модуль javascript. Я написал модуль для создания чистого URL-адреса, поэтому мне нужно транслитировать входную строку... (http://pid.github.io/speakingurl/)

var mySlug = require('speakingurl').createSlug({
    maintainCase: true,
    separator: " "
});

var input = "Schöner Titel läßt grüßen!? Bel été !";
var result;

slug = mySlug(input);
console.log(result); // Output: "Schoener Titel laesst gruessen bel ete"

Теперь вы можете сортировать с этими результатами. Вы можете отл. сохранить исходный заголовок в поле «title» и поле для сортировки в «title_sort» с результатом mySlug.

person pid    schedule 29.11.2013
comment
Это почти хорошее решение. Проблема в том, что ä будет смешано с a, но должно быть отделено. - person Tomasz Wysocki; 01.12.2013