Эффективно заменить все акцентированные символы в строке?


114

Для реализации бедного человека в ближайшем -collation-правильной сортировки на стороне клиента , мне нужна функция JavaScript , что делает эффективной замены одного символа в строке.

Вот что я имею в виду (обратите внимание, что это относится к немецкому тексту, другие языки сортируются по-другому):

родная сортировка ошибается: abcouz ä ö ü
правильное сопоставление будет: a ä bco ö u ü z

По сути, мне нужно, чтобы все вхождения «ä» в данной строке заменяли на «а» (и так далее). Таким образом, результат собственной сортировки будет очень близок к тому, что ожидал пользователь (или к тому, что вернет база данных).

В других языках есть средства для этого: Python предоставляетstr.translate() , Perl естьtr/…/…/ , XPath имеет функциюtranslate() , ColdFusion естьReplaceList() . А как насчет JavaScript?

Вот что у меня есть прямо сейчас.

// s would be a rather short string (something like 
// 200 characters at max, most of the time much less)
function makeSortString(s) {
  var translate = {
    "ä": "a", "ö": "o", "ü": "u",
    "Ä": "A", "Ö": "O", "Ü": "U"   // probably more to come
  };
  var translate_re = /[öäüÖÄÜ]/g;
  return ( s.replace(translate_re, function(match) { 
    return translate[match]; 
  }) );
}

Во-первых, мне не нравится, что регулярное выражение перестраивается каждый раз, когда я вызываю функцию. Я предполагаю, что закрытие может помочь в этом отношении, но я, кажется, по какой-то причине не разбираюсь в этом.

Кто-нибудь может придумать что-нибудь более эффективное?


Ответы ниже делятся на две категории:

  1. Функции замены строк разной степени полноты и эффективности (о чем я изначально спрашивал)
  2. Поздно упоминание о String#localeCompare, которая в настоящее время широко поддерживается среди двигателей JS (не так много , в то время вопроса) и может решить эту категорию проблемы гораздо более элегантно.

9
Вы ошибаетесь в своем предположении, что пользователь ожидает, что "ä" будет отсортировано с "a". В шведском алфавите 29 букв: abcdefghijklmnopqrstuvwxyzåäö, а также в датско-норвежском: abcdefghijklmnopqrstuvwxyzæøå. Ожидаемый порядок: «Апельсин», «Банан», «Аппле».
некоторые,

1
Я знаю. Решение предназначалось для сортировки немецкого текста. Даже там это не правильно , но достаточно хорошо для случая использования. Этот вопрос никогда не задумывался как поиск алгоритма «решает все проблемы».
Tomalak

1
Я немного перефразировал вопрос, чтобы прояснить это с самого начала.
Tomalak

1
@Tomalak: Я нашел ваш вопрос, когда переходил по ссылке из другого вопроса о «u» и «ü», и мне пришлось возразить. Но поскольку вы сейчас пояснили, что это было для немецкого языка, мне больше нечего возражать.
некоторые

4
@some: Я предпочитаю короткое обсуждение в комментариях, а не голосование против в любое время. К сожалению, здесь есть люди, которые сначала голосуют против, а потом задают вопросы (если вообще). Следствие: ваш комментарий был оценен по достоинству. :)
Tomalak

Ответы:


37

Я не могу говорить о том, что вы пытаетесь сделать конкретно с самой функцией, но если вам не нравится, что регулярное выражение создается каждый раз, вот два решения и некоторые предостережения по каждому из них.

Вот один из способов сделать это:

function makeSortString(s) {
  if(!makeSortString.translate_re) makeSortString.translate_re = /[öäüÖÄÜ]/g;
  var translate = {
    "ä": "a", "ö": "o", "ü": "u",
    "Ä": "A", "Ö": "O", "Ü": "U"   // probably more to come
  };
  return ( s.replace(makeSortString.translate_re, function(match) { 
    return translate[match]; 
  }) );
}

Это, очевидно, сделает регулярное выражение свойством самой функции. Единственное, что вам может не понравиться в этом (или, я думаю, зависит), это то, что регулярное выражение теперь можно изменять вне тела функции. Итак, кто-то может сделать это, чтобы изменить внутреннее используемое регулярное выражение:

makeSortString.translate_re = /[a-z]/g;

Так что вариант есть.

Один из способов получить закрытие и, таким образом, предотвратить изменение регулярного выражения кем-либо - это определить это как назначение анонимной функции следующим образом:

var makeSortString = (function() {
  var translate_re = /[öäüÖÄÜ]/g;
  return function(s) {
    var translate = {
      "ä": "a", "ö": "o", "ü": "u",
      "Ä": "A", "Ö": "O", "Ü": "U"   // probably more to come
    };
    return ( s.replace(translate_re, function(match) { 
      return translate[match]; 
    }) );
  }
})();

Надеюсь, это будет вам полезно.


ОБНОВЛЕНИЕ: еще рано, и я не знаю, почему раньше не видел очевидного, но также может быть полезно поместить translateобъект в закрытие:

var makeSortString = (function() {
  var translate_re = /[öäüÖÄÜ]/g;
  var translate = {
    "ä": "a", "ö": "o", "ü": "u",
    "Ä": "A", "Ö": "O", "Ü": "U"   // probably more to come
  };
  return function(s) {
    return ( s.replace(translate_re, function(match) { 
      return translate[match]; 
    }) );
  }
})();

1
Я пытаюсь сделать так, чтобы сортировка плагина jQuery tablesorter работала правильно для табличных данных на немецком языке. Плагин может использовать определяемую пользователем функцию для извлечения строки для сортировки, что я должен сделать, иначе полученный порядок сортировки будет неправильным.
Tomalak

Неужели эта функция настолько неэффективна? Что вы сделали с тестированием?
Джейсон Бантинг,

1
Я не хотел сказать, что моя реализация была неэффективной. Это почти самый эффективный способ сделать это, о чем я могу думать. Но я не могу придумать все, поэтому я надеялся, что существует какой-то действительно умный способ манипулирования строками, о котором я не знал.
Tomalak

Понятно - думаю, вашего решения достаточно; поскольку я мог увидеть применение этой функции в долгосрочной перспективе, я провел базовое тестирование. Я проделал 5000 итераций для строки из 200 символов, содержащей хотя бы один из этих символов, один раз каждые 8 ​​символов, и это заняло около 500 мс.
Джейсон Бантинг

7
Кодировка для венгерского регулярного выражения:var translate_re = /[éáűőúöüóíÉÁŰPŐÚÖÜÓÍ]/g; var translate = { "é": "e", "á": "a", "ű": "u", "ő": "o", "ú": "u", "ö": "o", "ü": "u", "ó": "o", "í": "i", "É": "E", "Á": "A", "Ű": "U", "Ő": "O", "Ú": "U", "Ö": "O", "Ü": "U", "Ó": "O", "Í": "I" };
zsitro

102

Вот более полная версия, основанная на стандарте Unicode, взятая отсюда: http://semplicewebsites.com/removing-accents-javascript

var Latinise={};Latinise.latin_map={"Á":"A",
"Ă":"A",
"Ắ":"A",
"Ặ":"A",
"Ằ":"A",
"Ẳ":"A",
"Ẵ":"A",
"Ǎ":"A",
"Â":"A",
"Ấ":"A",
"Ậ":"A",
"Ầ":"A",
"Ẩ":"A",
"Ẫ":"A",
"Ä":"A",
"Ǟ":"A",
"Ȧ":"A",
"Ǡ":"A",
"Ạ":"A",
"Ȁ":"A",
"À":"A",
"Ả":"A",
"Ȃ":"A",
"Ā":"A",
"Ą":"A",
"Å":"A",
"Ǻ":"A",
"Ḁ":"A",
"Ⱥ":"A",
"Ã":"A",
"Ꜳ":"AA",
"Æ":"AE",
"Ǽ":"AE",
"Ǣ":"AE",
"Ꜵ":"AO",
"Ꜷ":"AU",
"Ꜹ":"AV",
"Ꜻ":"AV",
"Ꜽ":"AY",
"Ḃ":"B",
"Ḅ":"B",
"Ɓ":"B",
"Ḇ":"B",
"Ƀ":"B",
"Ƃ":"B",
"Ć":"C",
"Č":"C",
"Ç":"C",
"Ḉ":"C",
"Ĉ":"C",
"Ċ":"C",
"Ƈ":"C",
"Ȼ":"C",
"Ď":"D",
"Ḑ":"D",
"Ḓ":"D",
"Ḋ":"D",
"Ḍ":"D",
"Ɗ":"D",
"Ḏ":"D",
"Dz":"D",
"Dž":"D",
"Đ":"D",
"Ƌ":"D",
"DZ":"DZ",
"DŽ":"DZ",
"É":"E",
"Ĕ":"E",
"Ě":"E",
"Ȩ":"E",
"Ḝ":"E",
"Ê":"E",
"Ế":"E",
"Ệ":"E",
"Ề":"E",
"Ể":"E",
"Ễ":"E",
"Ḙ":"E",
"Ë":"E",
"Ė":"E",
"Ẹ":"E",
"Ȅ":"E",
"È":"E",
"Ẻ":"E",
"Ȇ":"E",
"Ē":"E",
"Ḗ":"E",
"Ḕ":"E",
"Ę":"E",
"Ɇ":"E",
"Ẽ":"E",
"Ḛ":"E",
"Ꝫ":"ET",
"Ḟ":"F",
"Ƒ":"F",
"Ǵ":"G",
"Ğ":"G",
"Ǧ":"G",
"Ģ":"G",
"Ĝ":"G",
"Ġ":"G",
"Ɠ":"G",
"Ḡ":"G",
"Ǥ":"G",
"Ḫ":"H",
"Ȟ":"H",
"Ḩ":"H",
"Ĥ":"H",
"Ⱨ":"H",
"Ḧ":"H",
"Ḣ":"H",
"Ḥ":"H",
"Ħ":"H",
"Í":"I",
"Ĭ":"I",
"Ǐ":"I",
"Î":"I",
"Ï":"I",
"Ḯ":"I",
"İ":"I",
"Ị":"I",
"Ȉ":"I",
"Ì":"I",
"Ỉ":"I",
"Ȋ":"I",
"Ī":"I",
"Į":"I",
"Ɨ":"I",
"Ĩ":"I",
"Ḭ":"I",
"Ꝺ":"D",
"Ꝼ":"F",
"Ᵹ":"G",
"Ꞃ":"R",
"Ꞅ":"S",
"Ꞇ":"T",
"Ꝭ":"IS",
"Ĵ":"J",
"Ɉ":"J",
"Ḱ":"K",
"Ǩ":"K",
"Ķ":"K",
"Ⱪ":"K",
"Ꝃ":"K",
"Ḳ":"K",
"Ƙ":"K",
"Ḵ":"K",
"Ꝁ":"K",
"Ꝅ":"K",
"Ĺ":"L",
"Ƚ":"L",
"Ľ":"L",
"Ļ":"L",
"Ḽ":"L",
"Ḷ":"L",
"Ḹ":"L",
"Ⱡ":"L",
"Ꝉ":"L",
"Ḻ":"L",
"Ŀ":"L",
"Ɫ":"L",
"Lj":"L",
"Ł":"L",
"LJ":"LJ",
"Ḿ":"M",
"Ṁ":"M",
"Ṃ":"M",
"Ɱ":"M",
"Ń":"N",
"Ň":"N",
"Ņ":"N",
"Ṋ":"N",
"Ṅ":"N",
"Ṇ":"N",
"Ǹ":"N",
"Ɲ":"N",
"Ṉ":"N",
"Ƞ":"N",
"Nj":"N",
"Ñ":"N",
"NJ":"NJ",
"Ó":"O",
"Ŏ":"O",
"Ǒ":"O",
"Ô":"O",
"Ố":"O",
"Ộ":"O",
"Ồ":"O",
"Ổ":"O",
"Ỗ":"O",
"Ö":"O",
"Ȫ":"O",
"Ȯ":"O",
"Ȱ":"O",
"Ọ":"O",
"Ő":"O",
"Ȍ":"O",
"Ò":"O",
"Ỏ":"O",
"Ơ":"O",
"Ớ":"O",
"Ợ":"O",
"Ờ":"O",
"Ở":"O",
"Ỡ":"O",
"Ȏ":"O",
"Ꝋ":"O",
"Ꝍ":"O",
"Ō":"O",
"Ṓ":"O",
"Ṑ":"O",
"Ɵ":"O",
"Ǫ":"O",
"Ǭ":"O",
"Ø":"O",
"Ǿ":"O",
"Õ":"O",
"Ṍ":"O",
"Ṏ":"O",
"Ȭ":"O",
"Ƣ":"OI",
"Ꝏ":"OO",
"Ɛ":"E",
"Ɔ":"O",
"Ȣ":"OU",
"Ṕ":"P",
"Ṗ":"P",
"Ꝓ":"P",
"Ƥ":"P",
"Ꝕ":"P",
"Ᵽ":"P",
"Ꝑ":"P",
"Ꝙ":"Q",
"Ꝗ":"Q",
"Ŕ":"R",
"Ř":"R",
"Ŗ":"R",
"Ṙ":"R",
"Ṛ":"R",
"Ṝ":"R",
"Ȑ":"R",
"Ȓ":"R",
"Ṟ":"R",
"Ɍ":"R",
"Ɽ":"R",
"Ꜿ":"C",
"Ǝ":"E",
"Ś":"S",
"Ṥ":"S",
"Š":"S",
"Ṧ":"S",
"Ş":"S",
"Ŝ":"S",
"Ș":"S",
"Ṡ":"S",
"Ṣ":"S",
"Ṩ":"S",
"Ť":"T",
"Ţ":"T",
"Ṱ":"T",
"Ț":"T",
"Ⱦ":"T",
"Ṫ":"T",
"Ṭ":"T",
"Ƭ":"T",
"Ṯ":"T",
"Ʈ":"T",
"Ŧ":"T",
"Ɐ":"A",
"Ꞁ":"L",
"Ɯ":"M",
"Ʌ":"V",
"Ꜩ":"TZ",
"Ú":"U",
"Ŭ":"U",
"Ǔ":"U",
"Û":"U",
"Ṷ":"U",
"Ü":"U",
"Ǘ":"U",
"Ǚ":"U",
"Ǜ":"U",
"Ǖ":"U",
"Ṳ":"U",
"Ụ":"U",
"Ű":"U",
"Ȕ":"U",
"Ù":"U",
"Ủ":"U",
"Ư":"U",
"Ứ":"U",
"Ự":"U",
"Ừ":"U",
"Ử":"U",
"Ữ":"U",
"Ȗ":"U",
"Ū":"U",
"Ṻ":"U",
"Ų":"U",
"Ů":"U",
"Ũ":"U",
"Ṹ":"U",
"Ṵ":"U",
"Ꝟ":"V",
"Ṿ":"V",
"Ʋ":"V",
"Ṽ":"V",
"Ꝡ":"VY",
"Ẃ":"W",
"Ŵ":"W",
"Ẅ":"W",
"Ẇ":"W",
"Ẉ":"W",
"Ẁ":"W",
"Ⱳ":"W",
"Ẍ":"X",
"Ẋ":"X",
"Ý":"Y",
"Ŷ":"Y",
"Ÿ":"Y",
"Ẏ":"Y",
"Ỵ":"Y",
"Ỳ":"Y",
"Ƴ":"Y",
"Ỷ":"Y",
"Ỿ":"Y",
"Ȳ":"Y",
"Ɏ":"Y",
"Ỹ":"Y",
"Ź":"Z",
"Ž":"Z",
"Ẑ":"Z",
"Ⱬ":"Z",
"Ż":"Z",
"Ẓ":"Z",
"Ȥ":"Z",
"Ẕ":"Z",
"Ƶ":"Z",
"IJ":"IJ",
"Œ":"OE",
"ᴀ":"A",
"ᴁ":"AE",
"ʙ":"B",
"ᴃ":"B",
"ᴄ":"C",
"ᴅ":"D",
"ᴇ":"E",
"ꜰ":"F",
"ɢ":"G",
"ʛ":"G",
"ʜ":"H",
"ɪ":"I",
"ʁ":"R",
"ᴊ":"J",
"ᴋ":"K",
"ʟ":"L",
"ᴌ":"L",
"ᴍ":"M",
"ɴ":"N",
"ᴏ":"O",
"ɶ":"OE",
"ᴐ":"O",
"ᴕ":"OU",
"ᴘ":"P",
"ʀ":"R",
"ᴎ":"N",
"ᴙ":"R",
"ꜱ":"S",
"ᴛ":"T",
"ⱻ":"E",
"ᴚ":"R",
"ᴜ":"U",
"ᴠ":"V",
"ᴡ":"W",
"ʏ":"Y",
"ᴢ":"Z",
"á":"a",
"ă":"a",
"ắ":"a",
"ặ":"a",
"ằ":"a",
"ẳ":"a",
"ẵ":"a",
"ǎ":"a",
"â":"a",
"ấ":"a",
"ậ":"a",
"ầ":"a",
"ẩ":"a",
"ẫ":"a",
"ä":"a",
"ǟ":"a",
"ȧ":"a",
"ǡ":"a",
"ạ":"a",
"ȁ":"a",
"à":"a",
"ả":"a",
"ȃ":"a",
"ā":"a",
"ą":"a",
"ᶏ":"a",
"ẚ":"a",
"å":"a",
"ǻ":"a",
"ḁ":"a",
"ⱥ":"a",
"ã":"a",
"ꜳ":"aa",
"æ":"ae",
"ǽ":"ae",
"ǣ":"ae",
"ꜵ":"ao",
"ꜷ":"au",
"ꜹ":"av",
"ꜻ":"av",
"ꜽ":"ay",
"ḃ":"b",
"ḅ":"b",
"ɓ":"b",
"ḇ":"b",
"ᵬ":"b",
"ᶀ":"b",
"ƀ":"b",
"ƃ":"b",
"ɵ":"o",
"ć":"c",
"č":"c",
"ç":"c",
"ḉ":"c",
"ĉ":"c",
"ɕ":"c",
"ċ":"c",
"ƈ":"c",
"ȼ":"c",
"ď":"d",
"ḑ":"d",
"ḓ":"d",
"ȡ":"d",
"ḋ":"d",
"ḍ":"d",
"ɗ":"d",
"ᶑ":"d",
"ḏ":"d",
"ᵭ":"d",
"ᶁ":"d",
"đ":"d",
"ɖ":"d",
"ƌ":"d",
"ı":"i",
"ȷ":"j",
"ɟ":"j",
"ʄ":"j",
"dz":"dz",
"dž":"dz",
"é":"e",
"ĕ":"e",
"ě":"e",
"ȩ":"e",
"ḝ":"e",
"ê":"e",
"ế":"e",
"ệ":"e",
"ề":"e",
"ể":"e",
"ễ":"e",
"ḙ":"e",
"ë":"e",
"ė":"e",
"ẹ":"e",
"ȅ":"e",
"è":"e",
"ẻ":"e",
"ȇ":"e",
"ē":"e",
"ḗ":"e",
"ḕ":"e",
"ⱸ":"e",
"ę":"e",
"ᶒ":"e",
"ɇ":"e",
"ẽ":"e",
"ḛ":"e",
"ꝫ":"et",
"ḟ":"f",
"ƒ":"f",
"ᵮ":"f",
"ᶂ":"f",
"ǵ":"g",
"ğ":"g",
"ǧ":"g",
"ģ":"g",
"ĝ":"g",
"ġ":"g",
"ɠ":"g",
"ḡ":"g",
"ᶃ":"g",
"ǥ":"g",
"ḫ":"h",
"ȟ":"h",
"ḩ":"h",
"ĥ":"h",
"ⱨ":"h",
"ḧ":"h",
"ḣ":"h",
"ḥ":"h",
"ɦ":"h",
"ẖ":"h",
"ħ":"h",
"ƕ":"hv",
"í":"i",
"ĭ":"i",
"ǐ":"i",
"î":"i",
"ï":"i",
"ḯ":"i",
"ị":"i",
"ȉ":"i",
"ì":"i",
"ỉ":"i",
"ȋ":"i",
"ī":"i",
"į":"i",
"ᶖ":"i",
"ɨ":"i",
"ĩ":"i",
"ḭ":"i",
"ꝺ":"d",
"ꝼ":"f",
"ᵹ":"g",
"ꞃ":"r",
"ꞅ":"s",
"ꞇ":"t",
"ꝭ":"is",
"ǰ":"j",
"ĵ":"j",
"ʝ":"j",
"ɉ":"j",
"ḱ":"k",
"ǩ":"k",
"ķ":"k",
"ⱪ":"k",
"ꝃ":"k",
"ḳ":"k",
"ƙ":"k",
"ḵ":"k",
"ᶄ":"k",
"ꝁ":"k",
"ꝅ":"k",
"ĺ":"l",
"ƚ":"l",
"ɬ":"l",
"ľ":"l",
"ļ":"l",
"ḽ":"l",
"ȴ":"l",
"ḷ":"l",
"ḹ":"l",
"ⱡ":"l",
"ꝉ":"l",
"ḻ":"l",
"ŀ":"l",
"ɫ":"l",
"ᶅ":"l",
"ɭ":"l",
"ł":"l",
"lj":"lj",
"ſ":"s",
"ẜ":"s",
"ẛ":"s",
"ẝ":"s",
"ḿ":"m",
"ṁ":"m",
"ṃ":"m",
"ɱ":"m",
"ᵯ":"m",
"ᶆ":"m",
"ń":"n",
"ň":"n",
"ņ":"n",
"ṋ":"n",
"ȵ":"n",
"ṅ":"n",
"ṇ":"n",
"ǹ":"n",
"ɲ":"n",
"ṉ":"n",
"ƞ":"n",
"ᵰ":"n",
"ᶇ":"n",
"ɳ":"n",
"ñ":"n",
"nj":"nj",
"ó":"o",
"ŏ":"o",
"ǒ":"o",
"ô":"o",
"ố":"o",
"ộ":"o",
"ồ":"o",
"ổ":"o",
"ỗ":"o",
"ö":"o",
"ȫ":"o",
"ȯ":"o",
"ȱ":"o",
"ọ":"o",
"ő":"o",
"ȍ":"o",
"ò":"o",
"ỏ":"o",
"ơ":"o",
"ớ":"o",
"ợ":"o",
"ờ":"o",
"ở":"o",
"ỡ":"o",
"ȏ":"o",
"ꝋ":"o",
"ꝍ":"o",
"ⱺ":"o",
"ō":"o",
"ṓ":"o",
"ṑ":"o",
"ǫ":"o",
"ǭ":"o",
"ø":"o",
"ǿ":"o",
"õ":"o",
"ṍ":"o",
"ṏ":"o",
"ȭ":"o",
"ƣ":"oi",
"ꝏ":"oo",
"ɛ":"e",
"ᶓ":"e",
"ɔ":"o",
"ᶗ":"o",
"ȣ":"ou",
"ṕ":"p",
"ṗ":"p",
"ꝓ":"p",
"ƥ":"p",
"ᵱ":"p",
"ᶈ":"p",
"ꝕ":"p",
"ᵽ":"p",
"ꝑ":"p",
"ꝙ":"q",
"ʠ":"q",
"ɋ":"q",
"ꝗ":"q",
"ŕ":"r",
"ř":"r",
"ŗ":"r",
"ṙ":"r",
"ṛ":"r",
"ṝ":"r",
"ȑ":"r",
"ɾ":"r",
"ᵳ":"r",
"ȓ":"r",
"ṟ":"r",
"ɼ":"r",
"ᵲ":"r",
"ᶉ":"r",
"ɍ":"r",
"ɽ":"r",
"ↄ":"c",
"ꜿ":"c",
"ɘ":"e",
"ɿ":"r",
"ś":"s",
"ṥ":"s",
"š":"s",
"ṧ":"s",
"ş":"s",
"ŝ":"s",
"ș":"s",
"ṡ":"s",
"ṣ":"s",
"ṩ":"s",
"ʂ":"s",
"ᵴ":"s",
"ᶊ":"s",
"ȿ":"s",
"ɡ":"g",
"ᴑ":"o",
"ᴓ":"o",
"ᴝ":"u",
"ť":"t",
"ţ":"t",
"ṱ":"t",
"ț":"t",
"ȶ":"t",
"ẗ":"t",
"ⱦ":"t",
"ṫ":"t",
"ṭ":"t",
"ƭ":"t",
"ṯ":"t",
"ᵵ":"t",
"ƫ":"t",
"ʈ":"t",
"ŧ":"t",
"ᵺ":"th",
"ɐ":"a",
"ᴂ":"ae",
"ǝ":"e",
"ᵷ":"g",
"ɥ":"h",
"ʮ":"h",
"ʯ":"h",
"ᴉ":"i",
"ʞ":"k",
"ꞁ":"l",
"ɯ":"m",
"ɰ":"m",
"ᴔ":"oe",
"ɹ":"r",
"ɻ":"r",
"ɺ":"r",
"ⱹ":"r",
"ʇ":"t",
"ʌ":"v",
"ʍ":"w",
"ʎ":"y",
"ꜩ":"tz",
"ú":"u",
"ŭ":"u",
"ǔ":"u",
"û":"u",
"ṷ":"u",
"ü":"u",
"ǘ":"u",
"ǚ":"u",
"ǜ":"u",
"ǖ":"u",
"ṳ":"u",
"ụ":"u",
"ű":"u",
"ȕ":"u",
"ù":"u",
"ủ":"u",
"ư":"u",
"ứ":"u",
"ự":"u",
"ừ":"u",
"ử":"u",
"ữ":"u",
"ȗ":"u",
"ū":"u",
"ṻ":"u",
"ų":"u",
"ᶙ":"u",
"ů":"u",
"ũ":"u",
"ṹ":"u",
"ṵ":"u",
"ᵫ":"ue",
"ꝸ":"um",
"ⱴ":"v",
"ꝟ":"v",
"ṿ":"v",
"ʋ":"v",
"ᶌ":"v",
"ⱱ":"v",
"ṽ":"v",
"ꝡ":"vy",
"ẃ":"w",
"ŵ":"w",
"ẅ":"w",
"ẇ":"w",
"ẉ":"w",
"ẁ":"w",
"ⱳ":"w",
"ẘ":"w",
"ẍ":"x",
"ẋ":"x",
"ᶍ":"x",
"ý":"y",
"ŷ":"y",
"ÿ":"y",
"ẏ":"y",
"ỵ":"y",
"ỳ":"y",
"ƴ":"y",
"ỷ":"y",
"ỿ":"y",
"ȳ":"y",
"ẙ":"y",
"ɏ":"y",
"ỹ":"y",
"ź":"z",
"ž":"z",
"ẑ":"z",
"ʑ":"z",
"ⱬ":"z",
"ż":"z",
"ẓ":"z",
"ȥ":"z",
"ẕ":"z",
"ᵶ":"z",
"ᶎ":"z",
"ʐ":"z",
"ƶ":"z",
"ɀ":"z",
"ff":"ff",
"ffi":"ffi",
"ffl":"ffl",
"fi":"fi",
"fl":"fl",
"ij":"ij",
"œ":"oe",
"st":"st",
"ₐ":"a",
"ₑ":"e",
"ᵢ":"i",
"ⱼ":"j",
"ₒ":"o",
"ᵣ":"r",
"ᵤ":"u",
"ᵥ":"v",
"ₓ":"x"};
String.prototype.latinise=function(){return this.replace(/[^A-Za-z0-9\[\] ]/g,function(a){return Latinise.latin_map[a]||a})};
String.prototype.latinize=String.prototype.latinise;
String.prototype.isLatin=function(){return this==this.latinise()}

Некоторые примеры:

> "Piqué".latinize();
"Pique"
> "Piqué".isLatin();
false
> "Pique".isLatin();
true
> "Piqué".latinise().isLatin();
true

1
Спасибо, это, безусловно, полезно. Есть место для оптимизации, но это хорошее начало. +1
Tomalak

2
В чем смысл этой строки String.prototype.latinize=String.prototype.latinise;:?
zsitro

@zsitro Эта строка позволяет вызывать функцию через "äöü".latinize()и "äöü".latinise(). Не лучшая практика !!
yckart 01

3
Изменить прототип строки, это основная плохая практика. Я должен его обновить. В любом случае спасибо
Totty.js

Да - вы определенно можете избежать модификации прототипа - зависит от размера вашего проекта. Вы также можете выбрать предпочитаемое написание вместо того, чтобы раскрывать оба.
Ред.

33

Правильная терминология для таких акцентов - диакритические знаки . После поиска этого термина в Google я нашел эту функцию, которая является частью backbone.paginator. Он имеет очень полную коллекцию диакритических знаков и заменяет их наиболее интуитивно понятным символом ascii. Я обнаружил, что это наиболее полное решение Javascript, доступное на сегодняшний день.

Полная функция для использования в будущем:

function removeDiacritics (str) {

  var defaultDiacriticsRemovalMap = [
    {'base':'A', 'letters':/[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g},
    {'base':'AA','letters':/[\uA732]/g},
    {'base':'AE','letters':/[\u00C6\u01FC\u01E2]/g},
    {'base':'AO','letters':/[\uA734]/g},
    {'base':'AU','letters':/[\uA736]/g},
    {'base':'AV','letters':/[\uA738\uA73A]/g},
    {'base':'AY','letters':/[\uA73C]/g},
    {'base':'B', 'letters':/[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},
    {'base':'C', 'letters':/[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g},
    {'base':'D', 'letters':/[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g},
    {'base':'DZ','letters':/[\u01F1\u01C4]/g},
    {'base':'Dz','letters':/[\u01F2\u01C5]/g},
    {'base':'E', 'letters':/[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g},
    {'base':'F', 'letters':/[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},
    {'base':'G', 'letters':/[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g},
    {'base':'H', 'letters':/[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g},
    {'base':'I', 'letters':/[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g},
    {'base':'J', 'letters':/[\u004A\u24BF\uFF2A\u0134\u0248]/g},
    {'base':'K', 'letters':/[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g},
    {'base':'L', 'letters':/[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g},
    {'base':'LJ','letters':/[\u01C7]/g},
    {'base':'Lj','letters':/[\u01C8]/g},
    {'base':'M', 'letters':/[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},
    {'base':'N', 'letters':/[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g},
    {'base':'NJ','letters':/[\u01CA]/g},
    {'base':'Nj','letters':/[\u01CB]/g},
    {'base':'O', 'letters':/[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g},
    {'base':'OI','letters':/[\u01A2]/g},
    {'base':'OO','letters':/[\uA74E]/g},
    {'base':'OU','letters':/[\u0222]/g},
    {'base':'P', 'letters':/[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},
    {'base':'Q', 'letters':/[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},
    {'base':'R', 'letters':/[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g},
    {'base':'S', 'letters':/[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g},
    {'base':'T', 'letters':/[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g},
    {'base':'TZ','letters':/[\uA728]/g},
    {'base':'U', 'letters':/[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g},
    {'base':'V', 'letters':/[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},
    {'base':'VY','letters':/[\uA760]/g},
    {'base':'W', 'letters':/[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g},
    {'base':'X', 'letters':/[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},
    {'base':'Y', 'letters':/[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g},
    {'base':'Z', 'letters':/[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g},
    {'base':'a', 'letters':/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g},
    {'base':'aa','letters':/[\uA733]/g},
    {'base':'ae','letters':/[\u00E6\u01FD\u01E3]/g},
    {'base':'ao','letters':/[\uA735]/g},
    {'base':'au','letters':/[\uA737]/g},
    {'base':'av','letters':/[\uA739\uA73B]/g},
    {'base':'ay','letters':/[\uA73D]/g},
    {'base':'b', 'letters':/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g},
    {'base':'c', 'letters':/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g},
    {'base':'d', 'letters':/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g},
    {'base':'dz','letters':/[\u01F3\u01C6]/g},
    {'base':'e', 'letters':/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g},
    {'base':'f', 'letters':/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g},
    {'base':'g', 'letters':/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g},
    {'base':'h', 'letters':/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g},
    {'base':'hv','letters':/[\u0195]/g},
    {'base':'i', 'letters':/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g},
    {'base':'j', 'letters':/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g},
    {'base':'k', 'letters':/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g},
    {'base':'l', 'letters':/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g},
    {'base':'lj','letters':/[\u01C9]/g},
    {'base':'m', 'letters':/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g},
    {'base':'n', 'letters':/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g},
    {'base':'nj','letters':/[\u01CC]/g},
    {'base':'o', 'letters':/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g},
    {'base':'oi','letters':/[\u01A3]/g},
    {'base':'ou','letters':/[\u0223]/g},
    {'base':'oo','letters':/[\uA74F]/g},
    {'base':'p','letters':/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g},
    {'base':'q','letters':/[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g},
    {'base':'r','letters':/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g},
    {'base':'s','letters':/[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g},
    {'base':'t','letters':/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g},
    {'base':'tz','letters':/[\uA729]/g},
    {'base':'u','letters':/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g},
    {'base':'v','letters':/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g},
    {'base':'vy','letters':/[\uA761]/g},
    {'base':'w','letters':/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g},
    {'base':'x','letters':/[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g},
    {'base':'y','letters':/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g},
    {'base':'z','letters':/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g}
  ];

  for(var i=0; i<defaultDiacriticsRemovalMap.length; i++) {
    str = str.replace(defaultDiacriticsRemovalMap[i].letters, defaultDiacriticsRemovalMap[i].base);
  }

  return str;

}

Выглядит очень хорошо. - К сожалению, на момент написания этого вопроса backbone.js не существовало. :)
Tomalak

1
дополнительное обсуждение этого решения на stackoverflow.com/a/18391901/759452
Адриан Бе

22

https://stackoverflow.com/a/37511463

С ES2015 / ES6 String.Prototype.Normalize () ,

const str = "Crème Brulée"
str.normalize('NFD').replace(/[\u0300-\u036f]/g, "")
> 'Creme Brulee'

Здесь происходят две вещи:

  1. normalize()При NFDпреобразовании в нормальную форму Unicode комбинированные графемы разлагаются на комбинацию простых. èИз Crèmeконцов вверх выражается как e+̀ .
  2. Используя класс символов регулярного выражения для соответствия диапазону U + 0300 → U + 036F, теперь gлегко избавиться от диакритических знаков, которые стандарт Unicode удобно группирует как блок Unicode Combining Diacritical Marks .

См. Комментарий для тестирования производительности.

В качестве альтернативы, если вам просто нужна сортировка

Intl.Collator имеет достаточную поддержку ~ 85% прямо сейчас , polyfill также доступен здесь , но я не проверял.

const c = new Intl.Collator();
['creme brulee', 'crème brulée', 'crame brulai', 'crome brouillé',
'creme brulay', 'creme brulfé', 'creme bruléa'].sort(c.compare)
[ 'crame brulai','creme brulay','creme bruléa','creme brulee',
'crème brulée','creme brulfé','crome brouillé' ]


['creme brulee', 'crème brulée', 'crame brulai', 'crome brouillé'].sort((a,b) => a>b)
["crame brulai", "creme brulee", "crome brouillé", "crème brulée"]

1
Считаю этот ответ лучшим. На основе стандарта Unicode и с использованием встроенных функций. Спасибо.
DavidC

Intl.Collator(undefined , {sensitivity: 'base'})
Oliversisson

Я использовал это для создания заголовка, поэтому, прежде чем заменять пробелы на конечную косую черту и все на строчные буквы. Ваша функция работает отлично !!!
Саймон Бертон

Уже обсуждался в другом ответе в этой ветке за 14 год. stackoverflow.com/a/23767389/18771
Атируз

20

Просто следует нормализовать цепочку и запустить замену кодами:

var str = "Letras Á É Í Ó Ú Ñ - á é í ó ú ñ...";
console.log (str.normalize ("NFKD").replace (/[\u0300-\u036F]/g, ""));
// Letras A E I O U N - a e i o u n...

См. Нормализовать

Тогда вы можете использовать эту функцию:

function noTilde (s) {
    if (s.normalize != undefined) {
        s = s.normalize ("NFKD");
    }
    return s.replace (/[\u0300-\u036F]/g, "");
}

1
Это очень мило! Но с другой стороны, на момент написания он был передовым и вряд ли портативным.
Tomalak

может быть инкапсулирован в функцию
атируз

Всякая инкапсуляция будет бесполезна, если движок JS в браузере не поддерживает эту функцию.
Tomalak

На дворе 2016 год, а Safari по-прежнему его не поддерживает ... Жаль, что было бы очень удобно иметь этот инструмент под рукой.
Крис Кобрзак

2
Это не поддерживается в IE :(
начало

17

Я думаю, что это могло бы работать немного чище / лучше (хотя я не тестировал его производительность):

String.prototype.stripAccents = function() {
    var translate_re = /[àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ]/g;
    var translate = 'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY';
    return (this.replace(translate_re, function(match){
        return translate.substr(translate_re.source.indexOf(match)-1, 1); })
    );
};

Или, если вы все еще слишком беспокоитесь о производительности, давайте возьмем лучшее из обоих миров:

String.prototype.stripAccents = function() {
    var in_chrs =  'àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ',
        out_chrs = 'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY', 
        transl = {};
    eval('var chars_rgx = /['+in_chrs+']/g');
    for(var i = 0; i < in_chrs.length; i++){ transl[in_chrs.charAt(i)] = out_chrs.charAt(i); }
    return this.replace(chars_rgx, function(match){
        return transl[match]; });
};

РЕДАКТИРОВАТЬ (по @Tomalak)

Я ценю идею. Однако есть несколько ошибок в реализации, как указано в комментарии ниже.

Вот как я бы это реализовал.

var stripAccents = (function () {
  var in_chrs   = 'àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ',
      out_chrs  = 'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY', 
      chars_rgx = new RegExp('[' + in_chrs + ']', 'g'),
      transl    = {}, i,
      lookup    = function (m) { return transl[m] || m; };

  for (i=0; i<in_chrs.length; i++) {
    transl[ in_chrs[i] ] = out_chrs[i];
  }

  return function (s) { return s.replace(chars_rgx, lookup); }
})();

Почему вы думаете, что это работает лучше? Я предполагаю, что поиск объектов намного быстрее, чем String.indexOf().
Tomalak

Tomalak, я добавил еще один способ сделать это, в котором собрано лучшее из обоих миров (читаемость и производительность), я мог бы в конечном итоге сделать еще один шаг и кэшировать объект char_rgx, но я не думаю, что это имеет смысл, если только при работе с точность в реальном времени ...
Martin_Lakes

3
Извините, но в этом коде есть несколько ошибок. Во-первых, неправильное использование eval(). Для этого есть new RegExp(). Во-вторых, он изменяет прототип String. Модификация встроенных типов данных очень не одобряется. В-третьих, функция запускает цикл для каждого символа при каждом вызове. Это то, чего я пытался избежать в первую очередь. Это означает, что он исправляет удобочитаемость за счет производительности, что я считаю плохим компромиссом. Я ценю идею, но исполнение не оптимально. :)
Tomalak

@Tomalak, это отличный способ сделать это! Мне просто интересно, почему вы возвращаете функцию вместо того, чтобы передать "s" в первую очередьvar stripAccents = function(s){ var in_chrs = ... } ? jsfiddle
pmrotule

1
Поскольку возвращение функции закрывает переменные и функцию во внешней области видимости, поэтому их не нужно переопределять каждый раз при stripAccents()вызове. Смотрите закрытия.
Tomalak

16

Вот что я использую на основе решения Джейсона Бантинга.

Все это для подключаемого модуля jQuery tablesorter : для (почти правильной) сортировки неанглийских таблиц с помощью подключаемого модуля tablesorter необходимо использовать настраиваемую textExtractionфункцию .

Вот этот:

  • переводит самые распространенные буквы с ударением в буквы без ударения (список поддерживаемых букв легко расширяется)
  • изменяет даты в немецком формате ( 'dd.mm.yyyy') на распознанный формат ( 'yyyy-mm-dd')

Будьте осторожны, сохраняя файл JavaScript в кодировке UTF-8, иначе он не сработает.

// file encoding must be UTF-8!
function getTextExtractor()
{
  return (function() {
    var patternLetters = /[öäüÖÄÜáàâéèêúùûóòôÁÀÂÉÈÊÚÙÛÓÒÔß]/g;
    var patternDateDmy = /^(?:\D+)?(\d{1,2})\.(\d{1,2})\.(\d{2,4})$/;
    var lookupLetters = {
      "ä": "a", "ö": "o", "ü": "u",
      "Ä": "A", "Ö": "O", "Ü": "U",
      "á": "a", "à": "a", "â": "a",
      "é": "e", "è": "e", "ê": "e",
      "ú": "u", "ù": "u", "û": "u",
      "ó": "o", "ò": "o", "ô": "o",
      "Á": "A", "À": "A", "Â": "A",
      "É": "E", "È": "E", "Ê": "E",
      "Ú": "U", "Ù": "U", "Û": "U",
      "Ó": "O", "Ò": "O", "Ô": "O",
      "ß": "s"
    };
    var letterTranslator = function(match) { 
      return lookupLetters[match] || match;
    }

    return function(node) {
      var text = $.trim($(node).text());
      var date = text.match(patternDateDmy);
      if (date)
        return [date[3], date[2], date[1]].join("-");
      else
        return text.replace(patternLetters, letterTranslator);
    }
  })();
}

Вы можете использовать это так:

$("table.sortable").tablesorter({ 
  textExtraction: getTextExtractor()
}); 

Не знаю, увидит ли кто-нибудь мой комментарий, но мне нужна та же функция для некоторых акцентированных букв на португальском языке, и мне не удается заставить ее работать. Должны ли соответствующие буквы в моем php-файле вызываться «html-кодом»: & Iacute; или набрав букву "Í"? Пробовал оба, ничего не работает. И да, я изменил функцию js в соответствии со своими потребностями с помощью букв Í и í, а мой js закодирован в utf-8.
Кевин

1
@kevin: Конечно, кто-то заметил комментарий. ;-) Символ в вашем HTML (который, как я полагаю, создается этим файлом PHP) может быть &Iacute;или фактическим Í. Это не имеет значения, если настройки кодировки верны (фактическая кодировка файла PHP, кодировка файла, воспринимаемая сервером PHP, заголовок HTTP Content-Type, метатеги HTML). Использование HTML-объекта может быть самым безопасным. Если файл .js закодирован в UTF-8, он должен обслуживаться как таковой ( text/javascript; Charset=UTF-8), тогда все должно быть хорошо.
Tomalak

1
@kevin: Следующее: ваши скрипты обслуживаются Content-Type: text/htmlбез Charsetпараметра. По крайней мере, должны быть Content-Type: text/javascript;. Кроме того, ваш GetTextExtractor()метод (тот, что находится jquery.tablesorter.min.js) довольно сильно отличается от моей функции, не знаю, почему вы думаете, что ваш может работать. ;-) Совет: поместите scripts.jsсредство извлечения текста в код плагина tableorter, а не в него. Не трогайте код плагина, чтобы избежать головной боли в будущем.
Tomalak

1
@kevin: Мне жаль говорить, что есть причина чувствовать себя глупо. ;-) Вы скопировали мой код $("table.sortable").tablesorter(…);, но на самом деле ваша таблица$("table.tablesorter") . Также нет необходимости звонить tablesorter()второй раз. Как только вы внесете это изменение, оно будет работать - я только что тестировал через FireBug.
Tomalak

2
У меня все еще была проблема с сортировкой, например: Šalat, Sup. Это неправильный порядок, поэтому я сделал что-то вроде этого - «Š»: «Szz», «š»: «szz», это должно быть почти на 100% эффективным
mesnicka

11

Полное решение вашего запроса:

function convert_accented_characters(str){
    var conversions = new Object();
    conversions['ae'] = 'ä|æ|ǽ';
    conversions['oe'] = 'ö|œ';
    conversions['ue'] = 'ü';
    conversions['Ae'] = 'Ä';
    conversions['Ue'] = 'Ü';
    conversions['Oe'] = 'Ö';
    conversions['A'] = 'À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ';
    conversions['a'] = 'à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª';
    conversions['C'] = 'Ç|Ć|Ĉ|Ċ|Č';
    conversions['c'] = 'ç|ć|ĉ|ċ|č';
    conversions['D'] = 'Ð|Ď|Đ';
    conversions['d'] = 'ð|ď|đ';
    conversions['E'] = 'È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě';
    conversions['e'] = 'è|é|ê|ë|ē|ĕ|ė|ę|ě';
    conversions['G'] = 'Ĝ|Ğ|Ġ|Ģ';
    conversions['g'] = 'ĝ|ğ|ġ|ģ';
    conversions['H'] = 'Ĥ|Ħ';
    conversions['h'] = 'ĥ|ħ';
    conversions['I'] = 'Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ';
    conversions['i'] = 'ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı';
    conversions['J'] = 'Ĵ';
    conversions['j'] = 'ĵ';
    conversions['K'] = 'Ķ';
    conversions['k'] = 'ķ';
    conversions['L'] = 'Ĺ|Ļ|Ľ|Ŀ|Ł';
    conversions['l'] = 'ĺ|ļ|ľ|ŀ|ł';
    conversions['N'] = 'Ñ|Ń|Ņ|Ň';
    conversions['n'] = 'ñ|ń|ņ|ň|ʼn';
    conversions['O'] = 'Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ';
    conversions['o'] = 'ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º';
    conversions['R'] = 'Ŕ|Ŗ|Ř';
    conversions['r'] = 'ŕ|ŗ|ř';
    conversions['S'] = 'Ś|Ŝ|Ş|Š';
    conversions['s'] = 'ś|ŝ|ş|š|ſ';
    conversions['T'] = 'Ţ|Ť|Ŧ';
    conversions['t'] = 'ţ|ť|ŧ';
    conversions['U'] = 'Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ';
    conversions['u'] = 'ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ';
    conversions['Y'] = 'Ý|Ÿ|Ŷ';
    conversions['y'] = 'ý|ÿ|ŷ';
    conversions['W'] = 'Ŵ';
    conversions['w'] = 'ŵ';
    conversions['Z'] = 'Ź|Ż|Ž';
    conversions['z'] = 'ź|ż|ž';
    conversions['AE'] = 'Æ|Ǽ';
    conversions['ss'] = 'ß';
    conversions['IJ'] = 'IJ';
    conversions['ij'] = 'ij';
    conversions['OE'] = 'Œ';
    conversions['f'] = 'ƒ';
    for(var i in conversions){
        var re = new RegExp(conversions[i],"g");
        str = str.replace(re,i);
    }
    return str;
}

10

Если вы ищете специально способ преобразования символов с диакритическими знаками в символы без диакритических знаков, а не способ сортировки символов с диакритическими знаками, с небольшими изысками, можно использовать функцию String.localeCompare, чтобы найти основные латинские символы, соответствующие расширенные. Например, вы можете захотеть создать удобный для человека URL-адрес из заголовка страницы. Если да, вы можете сделать что-то вроде этого:

var baseChars = [];
for (var i = 97; i < 97 + 26; i++) {
  baseChars.push(String.fromCharCode(i));
}

//if needed, handle fancy compound characters
baseChars = baseChars.concat('ss,aa,ae,ao,au,av,ay,dz,hv,lj,nj,oi,ou,oo,tz,vy'.split(','));

function isUpperCase(c) { return c !== c.toLocaleLowerCase() }

function toBaseChar(c, opts) {
  opts = opts || {};
  //if (!('nonAlphaChar' in opts)) opts.nonAlphaChar = '';
  //if (!('noMatchChar' in opts)) opts.noMatchChar = '';
  if (!('locale' in opts)) opts.locale = 'en';

  var cOpts = {sensitivity: 'base'};

  //exit early for any non-alphabetical character
  if (c.localeCompare('9', opts.locale, cOpts) <= 0) return opts.nonAlphaChar === undefined ? c : opts.nonAlphaChar;

  for (var i = 0; i < baseChars.length; i++) {
    var baseChar = baseChars[i];

    var comp = c.localeCompare(baseChar, opts.locale, cOpts);
    if (comp == 0) return (isUpperCase(c)) ? baseChar.toUpperCase() : baseChar;
  }

  return opts.noMatchChar === undefined ? c : opts.noMatchChar;
}

function latinify(str, opts) {
  return str.replace(/[^\w\s\d]/g, function(c) {
    return toBaseChar(c, opts);
  })
}

// Example:
console.log(latinify('Čeština Tsėhesenėstsestotse Tshivenḓa Emigliàn–Rumagnòl Slovenščina Português Tiếng Việt Straße'))

// "Cestina Tsehesenestsestotse Tshivenda Emiglian–Rumagnol Slovenscina Portugues Tieng Viet Strasse"

Это должно работать достаточно хорошо, но если потребуется дальнейшая оптимизация, можно использовать двоичный поиск localeCompareв качестве компаратора для поиска базового символа. Обратите внимание, что регистр сохраняется, а параметры позволяют сохранять, заменять или удалять символы, которые не являются алфавитными или не имеют соответствующих латинских символов, которыми они могут быть заменены. Эта реализация более быстрая и гибкая и должна работать с новыми символами по мере их добавления. Недостатком является то, что составные символы, такие как 'ꝡ', должны обрабатываться специально, если они нуждаются в поддержке.


1
Это очень мило. Жаль, что поздним ответам на старые темы уделяется так мало внимания.
Tomalak

1
Самый лучший ответ здесь. Должен получить больше голосов (получил мое!)
Аврохом Исроэль

6

Я сделал прототипную версию этого:

String.prototype.strip = function() {
  var translate_re = /[öäüÖÄÜß ]/g;
  var translate = {
    "ä":"a", "ö":"o", "ü":"u",
    "Ä":"A", "Ö":"O", "Ü":"U",
    " ":"_", "ß":"ss"   // probably more to come
  };
    return (this.replace(translate_re, function(match){
        return translate[match];})
    );
};

Используйте как:

var teststring = 'ä ö ü Ä Ö Ü ß';
teststring.strip();

Это изменит строку на a_o_u_A_O_U_ss


это не работает. Однако , если я var newstr = teststring.strip();и console.log()что, то это работает - jsfiddle . Спасибо, мужик, это самый лаконичный и читаемый метод.
Андрейс

5

Основываясь на существующих ответах и ​​некоторых предложениях, я создал этот:

String.prototype.removeAccents = function() {

    var removalMap = {
        'A'  : /[AⒶAÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄ]/g,
        'AA' : /[Ꜳ]/g,
        'AE' : /[ÆǼǢ]/g,
        'AO' : /[Ꜵ]/g,
        'AU' : /[Ꜷ]/g,
        'AV' : /[ꜸꜺ]/g,
        'AY' : /[Ꜽ]/g,
        'B'  : /[BⒷBḂḄḆɃƂƁ]/g,
        'C'  : /[CⒸCĆĈĊČÇḈƇȻꜾ]/g,
        'D'  : /[DⒹDḊĎḌḐḒḎĐƋƊƉꝹ]/g,
        'DZ' : /[DZDŽ]/g,
        'Dz' : /[DzDž]/g,
        'E'  : /[EⒺEÈÉÊỀẾỄỂẼĒḔḖĔĖËẺĚȄȆẸỆȨḜĘḘḚƐƎ]/g,
        'F'  : /[FⒻFḞƑꝻ]/g,
        'G'  : /[GⒼGǴĜḠĞĠǦĢǤƓꞠꝽꝾ]/g,
        'H'  : /[HⒽHĤḢḦȞḤḨḪĦⱧⱵꞍ]/g,
        'I'  : /[IⒾIÌÍÎĨĪĬİÏḮỈǏȈȊỊĮḬƗ]/g,
        'J'  : /[JⒿJĴɈ]/g,
        'K'  : /[KⓀKḰǨḲĶḴƘⱩꝀꝂꝄꞢ]/g,
        'L'  : /[LⓁLĿĹĽḶḸĻḼḺŁȽⱢⱠꝈꝆꞀ]/g,
        'LJ' : /[LJ]/g,
        'Lj' : /[Lj]/g,
        'M'  : /[MⓂMḾṀṂⱮƜ]/g,
        'N'  : /[NⓃNǸŃÑṄŇṆŅṊṈȠƝꞐꞤ]/g,
        'NJ' : /[NJ]/g,
        'Nj' : /[Nj]/g,
        'O'  : /[OⓄOÒÓÔỒỐỖỔÕṌȬṎŌṐṒŎȮȰÖȪỎŐǑȌȎƠỜỚỠỞỢỌỘǪǬØǾƆƟꝊꝌ]/g,
        'OI' : /[Ƣ]/g,
        'OO' : /[Ꝏ]/g,
        'OU' : /[Ȣ]/g,
        'P'  : /[PⓅPṔṖƤⱣꝐꝒꝔ]/g,
        'Q'  : /[QⓆQꝖꝘɊ]/g,
        'R'  : /[RⓇRŔṘŘȐȒṚṜŖṞɌⱤꝚꞦꞂ]/g,
        'S'  : /[SⓈSẞŚṤŜṠŠṦṢṨȘŞⱾꞨꞄ]/g,
        'T'  : /[TⓉTṪŤṬȚŢṰṮŦƬƮȾꞆ]/g,
        'TZ' : /[Ꜩ]/g,
        'U'  : /[UⓊUÙÚÛŨṸŪṺŬÜǛǗǕǙỦŮŰǓȔȖƯỪỨỮỬỰỤṲŲṶṴɄ]/g,
        'V'  : /[VⓋVṼṾƲꝞɅ]/g,
        'VY' : /[Ꝡ]/g,
        'W'  : /[WⓌWẀẂŴẆẄẈⱲ]/g,
        'X'  : /[XⓍXẊẌ]/g,
        'Y'  : /[YⓎYỲÝŶỸȲẎŸỶỴƳɎỾ]/g,
        'Z'  : /[ZⓏZŹẐŻŽẒẔƵȤⱿⱫꝢ]/g,
        'a'  : /[aⓐaẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐ]/g,
        'aa' : /[ꜳ]/g,
        'ae' : /[æǽǣ]/g,
        'ao' : /[ꜵ]/g,
        'au' : /[ꜷ]/g,
        'av' : /[ꜹꜻ]/g,
        'ay' : /[ꜽ]/g,
        'b'  : /[bⓑbḃḅḇƀƃɓ]/g,
        'c'  : /[cⓒcćĉċčçḉƈȼꜿↄ]/g,
        'd'  : /[dⓓdḋďḍḑḓḏđƌɖɗꝺ]/g,
        'dz' : /[dzdž]/g,
        'e'  : /[eⓔeèéêềếễểẽēḕḗĕėëẻěȅȇẹệȩḝęḙḛɇɛǝ]/g,
        'f'  : /[fⓕfḟƒꝼ]/g,
        'g'  : /[gⓖgǵĝḡğġǧģǥɠꞡᵹꝿ]/g,
        'h'  : /[hⓗhĥḣḧȟḥḩḫẖħⱨⱶɥ]/g,
        'hv' : /[ƕ]/g,
        'i'  : /[iⓘiìíîĩīĭïḯỉǐȉȋịįḭɨı]/g,
        'j'  : /[jⓙjĵǰɉ]/g,
        'k'  : /[kⓚkḱǩḳķḵƙⱪꝁꝃꝅꞣ]/g,
        'l'  : /[lⓛlŀĺľḷḹļḽḻſłƚɫⱡꝉꞁꝇ]/g,
        'lj' : /[lj]/g,
        'm'  : /[mⓜmḿṁṃɱɯ]/g,
        'n'  : /[nⓝnǹńñṅňṇņṋṉƞɲʼnꞑꞥ]/g,
        'nj' : /[nj]/g,
        'o'  : /[oⓞoòóôồốỗổõṍȭṏōṑṓŏȯȱöȫỏőǒȍȏơờớỡởợọộǫǭøǿɔꝋꝍɵ]/g,
        'oi' : /[ƣ]/g,
        'ou' : /[ȣ]/g,
        'oo' : /[ꝏ]/g,
        'p'  : /[pⓟpṕṗƥᵽꝑꝓꝕ]/g,
        'q'  : /[qⓠqɋꝗꝙ]/g,
        'r'  : /[rⓡrŕṙřȑȓṛṝŗṟɍɽꝛꞧꞃ]/g,
        's'  : /[sⓢsßśṥŝṡšṧṣṩșşȿꞩꞅẛ]/g,
        't'  : /[tⓣtṫẗťṭțţṱṯŧƭʈⱦꞇ]/g,
        'tz' : /[ꜩ]/g,
        'u'  : /[uⓤuùúûũṹūṻŭüǜǘǖǚủůűǔȕȗưừứữửựụṳųṷṵʉ]/g,
        'v'  : /[vⓥvṽṿʋꝟʌ]/g,
        'vy' : /[ꝡ]/g,
        'w'  : /[wⓦwẁẃŵẇẅẘẉⱳ]/g,
        'x'  : /[xⓧxẋẍ]/g,
        'y'  : /[yⓨyỳýŷỹȳẏÿỷẙỵƴɏỿ]/g,
        'z'  : /[zⓩzźẑżžẓẕƶȥɀⱬꝣ]/g,
    };

    var str = this;

    for(var latin in removalMap) {
      var nonLatin = removalMap[latin];
      str = str.replace(nonLatin , latin);
    }

    return str;
}

Он использует настоящие символы вместо списка Unicode и хорошо работает.

Вы можете использовать это как

"ąąą".removeAccents(); // returns "aaa"

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


1
К сожалению, это сравнительно неэффективно с таким количеством регулярных выражений в цикле.
Tomalak

4

Прямой перенос на javascript решения Kierons: https://github.com/rwarasaurus/nano/blob/master/system/helpers.php#L61-73 :

/**
 * Normalise a string replacing foreign characters
 *
 * @param {String} str
 * @return {String} str
 */

var normalize = (function () {
    var a = ['À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'ß', 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē', 'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ', 'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń', 'ń', 'Ņ', 'ņ', 'Ň', 'ň', 'ʼn', 'Ō', 'ō', 'Ŏ', 'ŏ', 'Ő', 'ő', 'Œ', 'œ', 'Ŕ', 'ŕ', 'Ŗ', 'ŗ', 'Ř', 'ř', 'Ś', 'ś', 'Ŝ', 'ŝ', 'Ş', 'ş', 'Š', 'š', 'Ţ', 'ţ', 'Ť', 'ť', 'Ŧ', 'ŧ', 'Ũ', 'ũ', 'Ū', 'ū', 'Ŭ', 'ŭ', 'Ů', 'ů', 'Ű', 'ű', 'Ų', 'ų', 'Ŵ', 'ŵ', 'Ŷ', 'ŷ', 'Ÿ', 'Ź', 'ź', 'Ż', 'ż', 'Ž', 'ž', 'ſ', 'ƒ', 'Ơ', 'ơ', 'Ư', 'ư', 'Ǎ', 'ǎ', 'Ǐ', 'ǐ', 'Ǒ', 'ǒ', 'Ǔ', 'ǔ', 'Ǖ', 'ǖ', 'Ǘ', 'ǘ', 'Ǚ', 'ǚ', 'Ǜ', 'ǜ', 'Ǻ', 'ǻ', 'Ǽ', 'ǽ', 'Ǿ', 'ǿ'];
    var b = ['A', 'A', 'A', 'A', 'A', 'A', 'AE', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y', 's', 'a', 'a', 'a', 'a', 'a', 'a', 'ae', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'A', 'a', 'A', 'a', 'A', 'a', 'C', 'c', 'C', 'c', 'C', 'c', 'C', 'c', 'D', 'd', 'D', 'd', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'E', 'e', 'G', 'g', 'G', 'g', 'G', 'g', 'G', 'g', 'H', 'h', 'H', 'h', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'I', 'i', 'IJ', 'ij', 'J', 'j', 'K', 'k', 'L', 'l', 'L', 'l', 'L', 'l', 'L', 'l', 'l', 'l', 'N', 'n', 'N', 'n', 'N', 'n', 'n', 'O', 'o', 'O', 'o', 'O', 'o', 'OE', 'oe', 'R', 'r', 'R', 'r', 'R', 'r', 'S', 's', 'S', 's', 'S', 's', 'S', 's', 'T', 't', 'T', 't', 'T', 't', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'W', 'w', 'Y', 'y', 'Y', 'Z', 'z', 'Z', 'z', 'Z', 'z', 's', 'f', 'O', 'o', 'U', 'u', 'A', 'a', 'I', 'i', 'O', 'o', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'U', 'u', 'A', 'a', 'AE', 'ae', 'O', 'o'];

    return function (str) {
        var i = a.length;
        while (i--) str = str.replace(a[i], b[i]);
        return str;
    };
}());

И немного измененная версия, использующая char-map вместо двух массивов:

Чтобы сравнить эти два метода, я сделал простой тест: http://jsperf.com/replace-foreign-characters

/**
 * Normalise a string replacing foreign characters
 *
 * @param {String} str
 * @return {String}
 */
var normalize = (function () {
    var map = {
            "À": "A",
            "Á": "A",
            "Â": "A",
            "Ã": "A",
            "Ä": "A",
            "Å": "A",
            "Æ": "AE",
            "Ç": "C",
            "È": "E",
            "É": "E",
            "Ê": "E",
            "Ë": "E",
            "Ì": "I",
            "Í": "I",
            "Î": "I",
            "Ï": "I",
            "Ð": "D",
            "Ñ": "N",
            "Ò": "O",
            "Ó": "O",
            "Ô": "O",
            "Õ": "O",
            "Ö": "O",
            "Ø": "O",
            "Ù": "U",
            "Ú": "U",
            "Û": "U",
            "Ü": "U",
            "Ý": "Y",
            "ß": "s",
            "à": "a",
            "á": "a",
            "â": "a",
            "ã": "a",
            "ä": "a",
            "å": "a",
            "æ": "ae",
            "ç": "c",
            "è": "e",
            "é": "e",
            "ê": "e",
            "ë": "e",
            "ì": "i",
            "í": "i",
            "î": "i",
            "ï": "i",
            "ñ": "n",
            "ò": "o",
            "ó": "o",
            "ô": "o",
            "õ": "o",
            "ö": "o",
            "ø": "o",
            "ù": "u",
            "ú": "u",
            "û": "u",
            "ü": "u",
            "ý": "y",
            "ÿ": "y",
            "Ā": "A",
            "ā": "a",
            "Ă": "A",
            "ă": "a",
            "Ą": "A",
            "ą": "a",
            "Ć": "C",
            "ć": "c",
            "Ĉ": "C",
            "ĉ": "c",
            "Ċ": "C",
            "ċ": "c",
            "Č": "C",
            "č": "c",
            "Ď": "D",
            "ď": "d",
            "Đ": "D",
            "đ": "d",
            "Ē": "E",
            "ē": "e",
            "Ĕ": "E",
            "ĕ": "e",
            "Ė": "E",
            "ė": "e",
            "Ę": "E",
            "ę": "e",
            "Ě": "E",
            "ě": "e",
            "Ĝ": "G",
            "ĝ": "g",
            "Ğ": "G",
            "ğ": "g",
            "Ġ": "G",
            "ġ": "g",
            "Ģ": "G",
            "ģ": "g",
            "Ĥ": "H",
            "ĥ": "h",
            "Ħ": "H",
            "ħ": "h",
            "Ĩ": "I",
            "ĩ": "i",
            "Ī": "I",
            "ī": "i",
            "Ĭ": "I",
            "ĭ": "i",
            "Į": "I",
            "į": "i",
            "İ": "I",
            "ı": "i",
            "IJ": "IJ",
            "ij": "ij",
            "Ĵ": "J",
            "ĵ": "j",
            "Ķ": "K",
            "ķ": "k",
            "Ĺ": "L",
            "ĺ": "l",
            "Ļ": "L",
            "ļ": "l",
            "Ľ": "L",
            "ľ": "l",
            "Ŀ": "L",
            "ŀ": "l",
            "Ł": "l",
            "ł": "l",
            "Ń": "N",
            "ń": "n",
            "Ņ": "N",
            "ņ": "n",
            "Ň": "N",
            "ň": "n",
            "ʼn": "n",
            "Ō": "O",
            "ō": "o",
            "Ŏ": "O",
            "ŏ": "o",
            "Ő": "O",
            "ő": "o",
            "Œ": "OE",
            "œ": "oe",
            "Ŕ": "R",
            "ŕ": "r",
            "Ŗ": "R",
            "ŗ": "r",
            "Ř": "R",
            "ř": "r",
            "Ś": "S",
            "ś": "s",
            "Ŝ": "S",
            "ŝ": "s",
            "Ş": "S",
            "ş": "s",
            "Š": "S",
            "š": "s",
            "Ţ": "T",
            "ţ": "t",
            "Ť": "T",
            "ť": "t",
            "Ŧ": "T",
            "ŧ": "t",
            "Ũ": "U",
            "ũ": "u",
            "Ū": "U",
            "ū": "u",
            "Ŭ": "U",
            "ŭ": "u",
            "Ů": "U",
            "ů": "u",
            "Ű": "U",
            "ű": "u",
            "Ų": "U",
            "ų": "u",
            "Ŵ": "W",
            "ŵ": "w",
            "Ŷ": "Y",
            "ŷ": "y",
            "Ÿ": "Y",
            "Ź": "Z",
            "ź": "z",
            "Ż": "Z",
            "ż": "z",
            "Ž": "Z",
            "ž": "z",
            "ſ": "s",
            "ƒ": "f",
            "Ơ": "O",
            "ơ": "o",
            "Ư": "U",
            "ư": "u",
            "Ǎ": "A",
            "ǎ": "a",
            "Ǐ": "I",
            "ǐ": "i",
            "Ǒ": "O",
            "ǒ": "o",
            "Ǔ": "U",
            "ǔ": "u",
            "Ǖ": "U",
            "ǖ": "u",
            "Ǘ": "U",
            "ǘ": "u",
            "Ǚ": "U",
            "ǚ": "u",
            "Ǜ": "U",
            "ǜ": "u",
            "Ǻ": "A",
            "ǻ": "a",
            "Ǽ": "AE",
            "ǽ": "ae",
            "Ǿ": "O",
            "ǿ": "o"
        },
        nonWord = /\W/g,
        mapping = function (c) {
            return map[c] || c; 
        };


    return function (str) {
        return str.replace(nonWord, mapping);
    };
}());

Это строит карту персонажей с каждым вызовом replace()именно того, чего я пытался избежать. Использование /\W/- приятный штрих, даже если он попытается заменить все пробелы, цифры и знаки препинания.
Tomalak

Первый вопрос легко решить, добавив карту и функцию замены к внешнему замыканию, что я только что сделал.
Tomalak

... Я не понимаю вашу последнюю правку. Почему вы убрали функцию замены с крышки?
Tomalak

@Tomalak Мне казалось, что функциональные выражения немного медленнее, чем прямые вызовы. Однако после небольшого исследования я пришел к выводу, что в данном случае это не имеет смысла. Теперь лучше?
yckart 02

Да, теперь все в порядке. Сохраняете ли вы выражение функции в переменной и используете его (например mapping) или передаете выражение функции в качестве аргумента (например foo(function () {...}), как вы это делали в предыдущей версии), семантически не имеет значения. Последнее не является прямым вызовом, это просто выражение функции, которое никогда не сохраняется.
Tomalak

4

Ни в одном ответе не упоминается String.localeCompare, что делает именно то, что вы изначально хотели, но не то, о чем вы просите.

var list = ['a', 'b', 'c', 'o', 'u', 'z', 'ä', 'ö', 'ü'];

list.sort((a, b) => a.localeCompare(b));

console.log(list);

//Outputs ['a', 'ä', 'b', 'c', 'o', 'ö', 'u', 'ü', 'z']

Однако второй и третий параметры не поддерживаются старыми браузерами. Тем не менее, этот вариант стоит рассмотреть.


Хорошее дополнение! В этом конкретном случае я не мог повлиять на то, как сравниваются строки, так как это делается внутри TableSorter. Я мог только влиять на то, какие струны я хочу использовать. Поэтому замена их была на тот момент единственным вариантом. Возможно, в более современных версиях TableSorter лучше внутренняя обработка этих вещей.
Tomalak

Я добавил особое упоминание об этом ответе на вопрос.
Tomalak

4

Я не могу придумать более простого способа эффективно удалить все диакритические знаки из строки, чем использовать это удивительное решение .

Посмотрите это в действии:

var string = "öäüÖÄÜ";

var string_norm = string.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
console.log(string_norm);


2
Уже обсуждался в другом ответе в этой теме. stackoverflow.com/a/23767389/18771
Tomalak

@Tomalak Верно, я этого не заметил. В любом случае, я не удаляю свой ответ, потому что считаю, что лучше использовать «NFD» вместо «NFKD». Плюс у меня есть отрывок. : p
Takit Isy

3

Давным-давно я сделал это на Java и нашел другое решение, основанное на единственной строке, которая захватывает часть таблицы Unicode, которая была важна для преобразования - остальное было преобразовано в? или любой другой заменяющий символ. Поэтому я попытался преобразовать его в JavaScript. Имейте в виду, что я не эксперт по JS. :-)

TAB_00C0 = "AAAAAAACEEEEIIII" +
    "DNOOOOO*OUUUUYIs" +
    "aaaaaaaceeeeiiii" +
    "?nooooo/ouuuuy?y" +
    "AaAaAaCcCcCcCcDd" +
    "DdEeEeEeEeEeGgGg" +
    "GgGgHhHhIiIiIiIi" +
    "IiJjJjKkkLlLlLlL" +
    "lLlNnNnNnnNnOoOo" +
    "OoOoRrRrRrSsSsSs" +
    "SsTtTtTtUuUuUuUu" +
    "UuUuWwYyYZzZzZzF";

function stripDiacritics(source) {
    var result = source.split('');
    for (var i = 0; i < result.length; i++) {
        var c = source.charCodeAt(i);
        if (c >= 0x00c0 && c <= 0x017f) {
            result[i] = String.fromCharCode(TAB_00C0.charCodeAt(c - 0x00c0));
        } else if (c > 127) {
            result[i] = '?';
        }
    }
    return result.join('');
}

stripDiacritics("Šupa, čo? ľšťčžýæøåℌð")

Это преобразует большинство символов Unicode latin1 + 2. Невозможно перевести один символ в несколько. Я не знаю его производительности на JS, в Java это, безусловно, самое быстрое из распространенных решений (6-50x), нет карты, нет регулярного выражения, ничего. Он производит строгий вывод в формате ASCII, потенциально с потерей информации, но размер вывода соответствует входному.

Я протестировал фрагмент с помощью http://www.webtoolkitonline.com/javascript-tester.html, и он получил Supa, co? lstczyaoa??ожидаемый результат.


1
Это довольно здорово. Спасибо, что поделился!
Tomalak

1
Недавно я сравнил это с "Šupa, čo? ľšťčžýæøåℌð".normalize ("NFKD").replace (/[\u0300-\u036F]/g, "")и был удивлен, что normalize+ replace(регулярное выражение, заметьте) примерно в два раза быстрее! Я обвиняю эти вещи быть встроенные модули и массово оптимизированы, но это бесспорно. Другое дело, что это не совсем то же самое для некоторых персонажей. Результат: Supa, co? lstczyæøaHð- так æøðне разрешены, но, с другой стороны, он покрывает то, ℌðчто было вне диапазона моей таблицы. normalize+replaceЧестно говоря, я предпочитаю это знать .
virgo47

3

Я просто хотел опубликовать свое решение, используя String # localeCompare

const base_chars = [
  '1', '2', '3', '4', '5', '6', '7', '8', '9',
  '0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
  'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
  'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
  '-', '_', ' '
];
const fix = str => str.normalize('NFKD').split('')
    .map(c => base_chars.find(bc => bc.localeCompare(c, 'en', { sensitivity: 'base' })==0))
    .join('');

const str = 'OÒ óëå-123';
console.log(`fix(${str}) = ${fix(str)}`);


2

Если вы хотите добиться сортировки, где «ä» стоит после «a» и не рассматривается как то же самое, вы можете использовать такую ​​функцию, как моя.

Вы всегда можете изменить алфавит, чтобы получить разные или даже странные сортировки. Однако, если вы хотите, чтобы некоторые буквы были эквивалентными, вам нужно манипулировать строками, подобными a = a.replace(/ä/, 'a')или подобными, как многие уже ответили выше. Я добавил прописные буквы, если кто-то хочет, чтобы все слова в верхнем регистре были перед всеми словами в нижнем регистре (тогда вы должны пропустить .toLowerCase()).

function sortbyalphabet(a,b) {
        alphabet = "0123456789AaÀàÁáÂâÃãÄäBbCcÇçDdÈèÉéÊêËëFfGgHhÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöPpQqRrSsTtÙùÚúÛûÜüVvWwXxÝýŸÿZz";
        a = a.toLowerCase();
        b = b.toLowerCase();
        shorterone = (a.length > b.length ? a : b);
        for (i=0; i<shorterone.length; i++){
            diff = alphabet.indexOf(a.charAt(i)) - alphabet.indexOf(b.charAt(i));
            if (diff!=0){
                return diff;
            }
        }
        // sort the shorter first
        return a.length - b.length;
    }
    var n = ["ast", "Äste", "apfel", "äpfel", "à"];
    console.log(n.sort(sortbyalphabet));
    // should return ["apfel", "ast", "à", "äpfel", "äste"]

Идея хорошая, реализацию можно улучшить. 1) Вы не использовали varключевое слово. Это означает, что каждая объявленная вами переменная является глобальной. Это определенно не то, что вы имели в виду (в JS нет автоматической области действия функций). Забывание порождает varнеприятные ошибки. 2) Вы должны использовать закрытие вместо повторного определения алфавита при каждом вызове функции. 3) Вы не проводите ни проверку типов, ни строгие сравнения. - Я создал оптимизированную версию вашей функции здесь: jsperf.com/collation-string-sorting . И в Chrome, и в IE это примерно в 4 раза быстрее, чем ваш подход.
Tomalak

1

Простой и легкий способ:

function remove-accents(p){
c='áàãâäéèêëíìîïóòõôöúùûüçÁÀÃÂÄÉÈÊËÍÌÎÏÓÒÕÖÔÚÙÛÜÇ';s='aaaaaeeeeiiiiooooouuuucAAAAAEEEEIIIIOOOOOUUUUC';n='';for(i=0;i<p.length;i++){if(c.search(p.substr(i,1))>=0){n+=s.substr(c.search(p.substr(i,1)),1);} else{n+=p.substr(i,1);}} return n;
}

Так сделай это:

remove-accents("Thís ís ân accêntéd phráse");

Вывод:

"This is an accented phrase"

1

Ответ os Crisalin почти идеален. Просто улучшили производительность, чтобы избежать создания нового RegExp при каждом запуске.

var normalizeConversions = [
    { regex: new RegExp('ä|æ|ǽ', 'g'), clean: 'ae' },
    { regex: new RegExp('ö|œ', 'g'), clean: 'oe' },
    { regex: new RegExp('ü', 'g'), clean: 'ue' },
    { regex: new RegExp('Ä', 'g'), clean: 'Ae' },
    { regex: new RegExp('Ü', 'g'), clean: 'Ue' },
    { regex: new RegExp('Ö', 'g'), clean: 'Oe' },
    { regex: new RegExp('À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ', 'g'), clean: 'A' },
    { regex: new RegExp('à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª', 'g'), clean: 'a' },
    { regex: new RegExp('Ç|Ć|Ĉ|Ċ|Č', 'g'), clean: 'C' },
    { regex: new RegExp('ç|ć|ĉ|ċ|č', 'g'), clean: 'c' },
    { regex: new RegExp('Ð|Ď|Đ', 'g'), clean: 'D' },
    { regex: new RegExp('ð|ď|đ', 'g'), clean: 'd' },
    { regex: new RegExp('È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě', 'g'), clean: 'E' },
    { regex: new RegExp('è|é|ê|ë|ē|ĕ|ė|ę|ě', 'g'), clean: 'e' },
    { regex: new RegExp('Ĝ|Ğ|Ġ|Ģ', 'g'), clean: 'G' },
    { regex: new RegExp('ĝ|ğ|ġ|ģ', 'g'), clean: 'g' },
    { regex: new RegExp('Ĥ|Ħ', 'g'), clean: 'H' },
    { regex: new RegExp('ĥ|ħ', 'g'), clean: 'h' },
    { regex: new RegExp('Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ', 'g'), clean: 'I' },
    { regex: new RegExp('ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı', 'g'), clean: 'i' },
    { regex: new RegExp('Ĵ', 'g'), clean: 'J' },
    { regex: new RegExp('ĵ', 'g'), clean: 'j' },
    { regex: new RegExp('Ķ', 'g'), clean: 'K' },
    { regex: new RegExp('ķ', 'g'), clean: 'k' },
    { regex: new RegExp('Ĺ|Ļ|Ľ|Ŀ|Ł', 'g'), clean: 'L' },
    { regex: new RegExp('ĺ|ļ|ľ|ŀ|ł', 'g'), clean: 'l' },
    { regex: new RegExp('Ñ|Ń|Ņ|Ň', 'g'), clean: 'N' },
    { regex: new RegExp('ñ|ń|ņ|ň|ʼn', 'g'), clean: 'n' },
    { regex: new RegExp('Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ', 'g'), clean: 'O' },
    { regex: new RegExp('ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º', 'g'), clean: 'o' },
    { regex: new RegExp('Ŕ|Ŗ|Ř', 'g'), clean: 'R' },
    { regex: new RegExp('ŕ|ŗ|ř', 'g'), clean: 'r' },
    { regex: new RegExp('Ś|Ŝ|Ş|Š', 'g'), clean: 'S' },
    { regex: new RegExp('ś|ŝ|ş|š|ſ', 'g'), clean: 's' },
    { regex: new RegExp('Ţ|Ť|Ŧ', 'g'), clean: 'T' },
    { regex: new RegExp('ţ|ť|ŧ', 'g'), clean: 't' },
    { regex: new RegExp('Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ', 'g'), clean: 'U' },
    { regex: new RegExp('ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ', 'g'), clean: 'u' },
    { regex: new RegExp('Ý|Ÿ|Ŷ', 'g'), clean: 'Y' },
    { regex: new RegExp('ý|ÿ|ŷ', 'g'), clean: 'y' },
    { regex: new RegExp('Ŵ', 'g'), clean: 'W' },
    { regex: new RegExp('ŵ', 'g'), clean: 'w' },
    { regex: new RegExp('Ź|Ż|Ž', 'g'), clean: 'Z' },
    { regex: new RegExp('ź|ż|ž', 'g'), clean: 'z' },
    { regex: new RegExp('Æ|Ǽ', 'g'), clean: 'AE' },
    { regex: new RegExp('ß', 'g'), clean: 'ss' },
    { regex: new RegExp('IJ', 'g'), clean: 'IJ' },
    { regex: new RegExp('ij', 'g'), clean: 'ij' },
    { regex: new RegExp('Œ', 'g'), clean: 'OE' },
    { regex: new RegExp('ƒ', 'g'), clean: 'f' }
];

Использование:

function(str){
    normalizeConversions.forEach(function(normalizeEntry){
        str = str.replace(normalizeEntry.regex, normalizeEntry.clean);
    });
    return str;
};

Я думаю, вы можете сэкономить место, используя литералы регулярных выражений, а классы символов более эффективны, чем чередования. Однако реальным ударом по производительности будет выполнение такого количества регулярных выражений в одной строке. Regex работает медленно. 100 регулярных выражений медленные * 100. Гораздо эффективнее выполнить одно регулярное выражение, которое соответствует 100 символам, и искать замены, как это делает принятый ответ, чем выполнять 100 регулярных выражений в цикле. Вдобавок к этому, строки JS неизменяемы, поэтому вы выделяете (количество регулярных выражений - 1) выбрасываемые строки с помощью этого подхода, что тоже довольно расточительно.
Tomalak

Здесь есть 2 вещи: память и производительность обработки. Что касается использования памяти, вы правы, этот подход выделяет больше памяти, но сегодня все устройства имеют много памяти, и ее не так много памяти для выделения. Насчет производительности обработки, я думаю, вы ошибаетесь. Я не подбираю 100 символов и ищу замену. Я делаю то же самое, что и ответ Crisalin, но вместо того, чтобы создавать RegExp при каждом приращении цикла, я создаю их один раз, повторно использую их при каждом вызове. Используйте немного больше памяти, но гораздо быстрее.
rmpt

Вы применяете 100 (хорошо, сейчас 50) регулярных выражений в цикле, постоянно создавая новые строки в процессах. Это неэффективно. Попробуйте сами. Попробуйте и с длинными струнами.
Tomalak

Я просто не понимаю, где мой ответ хуже, чем ответ Крисалина Петровского. Я делаю то же самое, но быстрее. Не говорю, что это лучшее, но это улучшение решения Crisalin, и это была единственная цель моего ответа.
rmpt

Это могло быть. Я не сравниваю ваши подходы. Все, что я указываю в вашем подходе, применимо и к его. (Существует глобальный кеш для регулярных выражений, постоянное создание одних и тех же не влияет на производительность так сильно, как вы думаете.)
Tomalak

0

Я решил это по-другому, если хотите.

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

var text = "your input string";
var searchChars = ['Å','Ä','å','Ö','ö']; // add more charecter.
var replaceChars = ['A','A','a','O','o']; // exact same index to searchChars.
var index;
for (var i = 0; i < text.length; i++) {
  if( $.inArray(text[i], searchChars) >-1 ){ // $.inArray() is from jquery.
    index = searchChars.indexOf(text[i]);
    text = text.slice(0, i) + replaceChars[index] + text.slice(i+1,text.length);
  }
}


1
Это крайне неэффективно. Вам будет полезно выбрать одно из других решений.
Tomalak

0

Для ребят с использованием машинописи и теми , кто не хочет иметь дело со строковыми прототипами, вот версия машинописи Эда ответа. :

    // Usage example:
    "Some string".replace(/[^a-zA-Z0-9-_]/g, char => ToLatinMap.get(char) || '')

    // Map:
    export let ToLatinMap: Map<string, string> = new Map<string, string>([
        ["Á", "A"],
        ["Ă", "A"],
        ["Ắ", "A"],
        ["Ặ", "A"],
        ["Ằ", "A"],
        ["Ẳ", "A"],
        ["Ẵ", "A"],
        ["Ǎ", "A"],
        ["Â", "A"],
        ["Ấ", "A"],
        ["Ậ", "A"],
        ["Ầ", "A"],
        ["Ẩ", "A"],
        ["Ẫ", "A"],
        ["Ä", "A"],
        ["Ǟ", "A"],
        ["Ȧ", "A"],
        ["Ǡ", "A"],
        ["Ạ", "A"],
        ["Ȁ", "A"],
        ["À", "A"],
        ["Ả", "A"],
        ["Ȃ", "A"],
        ["Ā", "A"],
        ["Ą", "A"],
        ["Å", "A"],
        ["Ǻ", "A"],
        ["Ḁ", "A"],
        ["Ⱥ", "A"],
        ["Ã", "A"],
        ["Ꜳ", "AA"],
        ["Æ", "AE"],
        ["Ǽ", "AE"],
        ["Ǣ", "AE"],
        ["Ꜵ", "AO"],
        ["Ꜷ", "AU"],
        ["Ꜹ", "AV"],
        ["Ꜻ", "AV"],
        ["Ꜽ", "AY"],
        ["Ḃ", "B"],
        ["Ḅ", "B"],
        ["Ɓ", "B"],
        ["Ḇ", "B"],
        ["Ƀ", "B"],
        ["Ƃ", "B"],
        ["Ć", "C"],
        ["Č", "C"],
        ["Ç", "C"],
        ["Ḉ", "C"],
        ["Ĉ", "C"],
        ["Ċ", "C"],
        ["Ƈ", "C"],
        ["Ȼ", "C"],
        ["Ď", "D"],
        ["Ḑ", "D"],
        ["Ḓ", "D"],
        ["Ḋ", "D"],
        ["Ḍ", "D"],
        ["Ɗ", "D"],
        ["Ḏ", "D"],
        ["Dz", "D"],
        ["Dž", "D"],
        ["Đ", "D"],
        ["Ƌ", "D"],
        ["DZ", "DZ"],
        ["DŽ", "DZ"],
        ["É", "E"],
        ["Ĕ", "E"],
        ["Ě", "E"],
        ["Ȩ", "E"],
        ["Ḝ", "E"],
        ["Ê", "E"],
        ["Ế", "E"],
        ["Ệ", "E"],
        ["Ề", "E"],
        ["Ể", "E"],
        ["Ễ", "E"],
        ["Ḙ", "E"],
        ["Ë", "E"],
        ["Ė", "E"],
        ["Ẹ", "E"],
        ["Ȅ", "E"],
        ["È", "E"],
        ["Ẻ", "E"],
        ["Ȇ", "E"],
        ["Ē", "E"],
        ["Ḗ", "E"],
        ["Ḕ", "E"],
        ["Ę", "E"],
        ["Ɇ", "E"],
        ["Ẽ", "E"],
        ["Ḛ", "E"],
        ["Ꝫ", "ET"],
        ["Ḟ", "F"],
        ["Ƒ", "F"],
        ["Ǵ", "G"],
        ["Ğ", "G"],
        ["Ǧ", "G"],
        ["Ģ", "G"],
        ["Ĝ", "G"],
        ["Ġ", "G"],
        ["Ɠ", "G"],
        ["Ḡ", "G"],
        ["Ǥ", "G"],
        ["Ḫ", "H"],
        ["Ȟ", "H"],
        ["Ḩ", "H"],
        ["Ĥ", "H"],
        ["Ⱨ", "H"],
        ["Ḧ", "H"],
        ["Ḣ", "H"],
        ["Ḥ", "H"],
        ["Ħ", "H"],
        ["Í", "I"],
        ["Ĭ", "I"],
        ["Ǐ", "I"],
        ["Î", "I"],
        ["Ï", "I"],
        ["Ḯ", "I"],
        ["İ", "I"],
        ["Ị", "I"],
        ["Ȉ", "I"],
        ["Ì", "I"],
        ["Ỉ", "I"],
        ["Ȋ", "I"],
        ["Ī", "I"],
        ["Į", "I"],
        ["Ɨ", "I"],
        ["Ĩ", "I"],
        ["Ḭ", "I"],
        ["Ꝺ", "D"],
        ["Ꝼ", "F"],
        ["Ᵹ", "G"],
        ["Ꞃ", "R"],
        ["Ꞅ", "S"],
        ["Ꞇ", "T"],
        ["Ꝭ", "IS"],
        ["Ĵ", "J"],
        ["Ɉ", "J"],
        ["Ḱ", "K"],
        ["Ǩ", "K"],
        ["Ķ", "K"],
        ["Ⱪ", "K"],
        ["Ꝃ", "K"],
        ["Ḳ", "K"],
        ["Ƙ", "K"],
        ["Ḵ", "K"],
        ["Ꝁ", "K"],
        ["Ꝅ", "K"],
        ["Ĺ", "L"],
        ["Ƚ", "L"],
        ["Ľ", "L"],
        ["Ļ", "L"],
        ["Ḽ", "L"],
        ["Ḷ", "L"],
        ["Ḹ", "L"],
        ["Ⱡ", "L"],
        ["Ꝉ", "L"],
        ["Ḻ", "L"],
        ["Ŀ", "L"],
        ["Ɫ", "L"],
        ["Lj", "L"],
        ["Ł", "L"],
        ["LJ", "LJ"],
        ["Ḿ", "M"],
        ["Ṁ", "M"],
        ["Ṃ", "M"],
        ["Ɱ", "M"],
        ["Ń", "N"],
        ["Ň", "N"],
        ["Ņ", "N"],
        ["Ṋ", "N"],
        ["Ṅ", "N"],
        ["Ṇ", "N"],
        ["Ǹ", "N"],
        ["Ɲ", "N"],
        ["Ṉ", "N"],
        ["Ƞ", "N"],
        ["Nj", "N"],
        ["Ñ", "N"],
        ["NJ", "NJ"],
        ["Ó", "O"],
        ["Ŏ", "O"],
        ["Ǒ", "O"],
        ["Ô", "O"],
        ["Ố", "O"],
        ["Ộ", "O"],
        ["Ồ", "O"],
        ["Ổ", "O"],
        ["Ỗ", "O"],
        ["Ö", "O"],
        ["Ȫ", "O"],
        ["Ȯ", "O"],
        ["Ȱ", "O"],
        ["Ọ", "O"],
        ["Ő", "O"],
        ["Ȍ", "O"],
        ["Ò", "O"],
        ["Ỏ", "O"],
        ["Ơ", "O"],
        ["Ớ", "O"],
        ["Ợ", "O"],
        ["Ờ", "O"],
        ["Ở", "O"],
        ["Ỡ", "O"],
        ["Ȏ", "O"],
        ["Ꝋ", "O"],
        ["Ꝍ", "O"],
        ["Ō", "O"],
        ["Ṓ", "O"],
        ["Ṑ", "O"],
        ["Ɵ", "O"],
        ["Ǫ", "O"],
        ["Ǭ", "O"],
        ["Ø", "O"],
        ["Ǿ", "O"],
        ["Õ", "O"],
        ["Ṍ", "O"],
        ["Ṏ", "O"],
        ["Ȭ", "O"],
        ["Ƣ", "OI"],
        ["Ꝏ", "OO"],
        ["Ɛ", "E"],
        ["Ɔ", "O"],
        ["Ȣ", "OU"],
        ["Ṕ", "P"],
        ["Ṗ", "P"],
        ["Ꝓ", "P"],
        ["Ƥ", "P"],
        ["Ꝕ", "P"],
        ["Ᵽ", "P"],
        ["Ꝑ", "P"],
        ["Ꝙ", "Q"],
        ["Ꝗ", "Q"],
        ["Ŕ", "R"],
        ["Ř", "R"],
        ["Ŗ", "R"],
        ["Ṙ", "R"],
        ["Ṛ", "R"],
        ["Ṝ", "R"],
        ["Ȑ", "R"],
        ["Ȓ", "R"],
        ["Ṟ", "R"],
        ["Ɍ", "R"],
        ["Ɽ", "R"],
        ["Ꜿ", "C"],
        ["Ǝ", "E"],
        ["Ś", "S"],
        ["Ṥ", "S"],
        ["Š", "S"],
        ["Ṧ", "S"],
        ["Ş", "S"],
        ["Ŝ", "S"],
        ["Ș", "S"],
        ["Ṡ", "S"],
        ["Ṣ", "S"],
        ["Ṩ", "S"],
        ["Ť", "T"],
        ["Ţ", "T"],
        ["Ṱ", "T"],
        ["Ț", "T"],
        ["Ⱦ", "T"],
        ["Ṫ", "T"],
        ["Ṭ", "T"],
        ["Ƭ", "T"],
        ["Ṯ", "T"],
        ["Ʈ", "T"],
        ["Ŧ", "T"],
        ["Ɐ", "A"],
        ["Ꞁ", "L"],
        ["Ɯ", "M"],
        ["Ʌ", "V"],
        ["Ꜩ", "TZ"],
        ["Ú", "U"],
        ["Ŭ", "U"],
        ["Ǔ", "U"],
        ["Û", "U"],
        ["Ṷ", "U"],
        ["Ü", "U"],
        ["Ǘ", "U"],
        ["Ǚ", "U"],
        ["Ǜ", "U"],
        ["Ǖ", "U"],
        ["Ṳ", "U"],
        ["Ụ", "U"],
        ["Ű", "U"],
        ["Ȕ", "U"],
        ["Ù", "U"],
        ["Ủ", "U"],
        ["Ư", "U"],
        ["Ứ", "U"],
        ["Ự", "U"],
        ["Ừ", "U"],
        ["Ử", "U"],
        ["Ữ", "U"],
        ["Ȗ", "U"],
        ["Ū", "U"],
        ["Ṻ", "U"],
        ["Ų", "U"],
        ["Ů", "U"],
        ["Ũ", "U"],
        ["Ṹ", "U"],
        ["Ṵ", "U"],
        ["Ꝟ", "V"],
        ["Ṿ", "V"],
        ["Ʋ", "V"],
        ["Ṽ", "V"],
        ["Ꝡ", "VY"],
        ["Ẃ", "W"],
        ["Ŵ", "W"],
        ["Ẅ", "W"],
        ["Ẇ", "W"],
        ["Ẉ", "W"],
        ["Ẁ", "W"],
        ["Ⱳ", "W"],
        ["Ẍ", "X"],
        ["Ẋ", "X"],
        ["Ý", "Y"],
        ["Ŷ", "Y"],
        ["Ÿ", "Y"],
        ["Ẏ", "Y"],
        ["Ỵ", "Y"],
        ["Ỳ", "Y"],
        ["Ƴ", "Y"],
        ["Ỷ", "Y"],
        ["Ỿ", "Y"],
        ["Ȳ", "Y"],
        ["Ɏ", "Y"],
        ["Ỹ", "Y"],
        ["Ź", "Z"],
        ["Ž", "Z"],
        ["Ẑ", "Z"],
        ["Ⱬ", "Z"],
        ["Ż", "Z"],
        ["Ẓ", "Z"],
        ["Ȥ", "Z"],
        ["Ẕ", "Z"],
        ["Ƶ", "Z"],
        ["IJ", "IJ"],
        ["Œ", "OE"],
        ["ᴀ", "A"],
        ["ᴁ", "AE"],
        ["ʙ", "B"],
        ["ᴃ", "B"],
        ["ᴄ", "C"],
        ["ᴅ", "D"],
        ["ᴇ", "E"],
        ["ꜰ", "F"],
        ["ɢ", "G"],
        ["ʛ", "G"],
        ["ʜ", "H"],
        ["ɪ", "I"],
        ["ʁ", "R"],
        ["ᴊ", "J"],
        ["ᴋ", "K"],
        ["ʟ", "L"],
        ["ᴌ", "L"],
        ["ᴍ", "M"],
        ["ɴ", "N"],
        ["ᴏ", "O"],
        ["ɶ", "OE"],
        ["ᴐ", "O"],
        ["ᴕ", "OU"],
        ["ᴘ", "P"],
        ["ʀ", "R"],
        ["ᴎ", "N"],
        ["ᴙ", "R"],
        ["ꜱ", "S"],
        ["ᴛ", "T"],
        ["ⱻ", "E"],
        ["ᴚ", "R"],
        ["ᴜ", "U"],
        ["ᴠ", "V"],
        ["ᴡ", "W"],
        ["ʏ", "Y"],
        ["ᴢ", "Z"],
        ["á", "a"],
        ["ă", "a"],
        ["ắ", "a"],
        ["ặ", "a"],
        ["ằ", "a"],
        ["ẳ", "a"],
        ["ẵ", "a"],
        ["ǎ", "a"],
        ["â", "a"],
        ["ấ", "a"],
        ["ậ", "a"],
        ["ầ", "a"],
        ["ẩ", "a"],
        ["ẫ", "a"],
        ["ä", "a"],
        ["ǟ", "a"],
        ["ȧ", "a"],
        ["ǡ", "a"],
        ["ạ", "a"],
        ["ȁ", "a"],
        ["à", "a"],
        ["ả", "a"],
        ["ȃ", "a"],
        ["ā", "a"],
        ["ą", "a"],
        ["ᶏ", "a"],
        ["ẚ", "a"],
        ["å", "a"],
        ["ǻ", "a"],
        ["ḁ", "a"],
        ["ⱥ", "a"],
        ["ã", "a"],
        ["ꜳ", "aa"],
        ["æ", "ae"],
        ["ǽ", "ae"],
        ["ǣ", "ae"],
        ["ꜵ", "ao"],
        ["ꜷ", "au"],
        ["ꜹ", "av"],
        ["ꜻ", "av"],
        ["ꜽ", "ay"],
        ["ḃ", "b"],
        ["ḅ", "b"],
        ["ɓ", "b"],
        ["ḇ", "b"],
        ["ᵬ", "b"],
        ["ᶀ", "b"],
        ["ƀ", "b"],
        ["ƃ", "b"],
        ["ɵ", "o"],
        ["ć", "c"],
        ["č", "c"],
        ["ç", "c"],
        ["ḉ", "c"],
        ["ĉ", "c"],
        ["ɕ", "c"],
        ["ċ", "c"],
        ["ƈ", "c"],
        ["ȼ", "c"],
        ["ď", "d"],
        ["ḑ", "d"],
        ["ḓ", "d"],
        ["ȡ", "d"],
        ["ḋ", "d"],
        ["ḍ", "d"],
        ["ɗ", "d"],
        ["ᶑ", "d"],
        ["ḏ", "d"],
        ["ᵭ", "d"],
        ["ᶁ", "d"],
        ["đ", "d"],
        ["ɖ", "d"],
        ["ƌ", "d"],
        ["ı", "i"],
        ["ȷ", "j"],
        ["ɟ", "j"],
        ["ʄ", "j"],
        ["dz", "dz"],
        ["dž", "dz"],
        ["é", "e"],
        ["ĕ", "e"],
        ["ě", "e"],
        ["ȩ", "e"],
        ["ḝ", "e"],
        ["ê", "e"],
        ["ế", "e"],
        ["ệ", "e"],
        ["ề", "e"],
        ["ể", "e"],
        ["ễ", "e"],
        ["ḙ", "e"],
        ["ë", "e"],
        ["ė", "e"],
        ["ẹ", "e"],
        ["ȅ", "e"],
        ["è", "e"],
        ["ẻ", "e"],
        ["ȇ", "e"],
        ["ē", "e"],
        ["ḗ", "e"],
        ["ḕ", "e"],
        ["ⱸ", "e"],
        ["ę", "e"],
        ["ᶒ", "e"],
        ["ɇ", "e"],
        ["ẽ", "e"],
        ["ḛ", "e"],
        ["ꝫ", "et"],
        ["ḟ", "f"],
        ["ƒ", "f"],
        ["ᵮ", "f"],
        ["ᶂ", "f"],
        ["ǵ", "g"],
        ["ğ", "g"],
        ["ǧ", "g"],
        ["ģ", "g"],
        ["ĝ", "g"],
        ["ġ", "g"],
        ["ɠ", "g"],
        ["ḡ", "g"],
        ["ᶃ", "g"],
        ["ǥ", "g"],
        ["ḫ", "h"],
        ["ȟ", "h"],
        ["ḩ", "h"],
        ["ĥ", "h"],
        ["ⱨ", "h"],
        ["ḧ", "h"],
        ["ḣ", "h"],
        ["ḥ", "h"],
        ["ɦ", "h"],
        ["ẖ", "h"],
        ["ħ", "h"],
        ["ƕ", "hv"],
        ["í", "i"],
        ["ĭ", "i"],
        ["ǐ", "i"],
        ["î", "i"],
        ["ï", "i"],
        ["ḯ", "i"],
        ["ị", "i"],
        ["ȉ", "i"],
        ["ì", "i"],
        ["ỉ", "i"],
        ["ȋ", "i"],
        ["ī", "i"],
        ["į", "i"],
        ["ᶖ", "i"],
        ["ɨ", "i"],
        ["ĩ", "i"],
        ["ḭ", "i"],
        ["ꝺ", "d"],
        ["ꝼ", "f"],
        ["ᵹ", "g"],
        ["ꞃ", "r"],
        ["ꞅ", "s"],
        ["ꞇ", "t"],
        ["ꝭ", "is"],
        ["ǰ", "j"],
        ["ĵ", "j"],
        ["ʝ", "j"],
        ["ɉ", "j"],
        ["ḱ", "k"],
        ["ǩ", "k"],
        ["ķ", "k"],
        ["ⱪ", "k"],
        ["ꝃ", "k"],
        ["ḳ", "k"],
        ["ƙ", "k"],
        ["ḵ", "k"],
        ["ᶄ", "k"],
        ["ꝁ", "k"],
        ["ꝅ", "k"],
        ["ĺ", "l"],
        ["ƚ", "l"],
        ["ɬ", "l"],
        ["ľ", "l"],
        ["ļ", "l"],
        ["ḽ", "l"],
        ["ȴ", "l"],
        ["ḷ", "l"],
        ["ḹ", "l"],
        ["ⱡ", "l"],
        ["ꝉ", "l"],
        ["ḻ", "l"],
        ["ŀ", "l"],
        ["ɫ", "l"],
        ["ᶅ", "l"],
        ["ɭ", "l"],
        ["ł", "l"],
        ["lj", "lj"],
        ["ſ", "s"],
        ["ẜ", "s"],
        ["ẛ", "s"],
        ["ẝ", "s"],
        ["ḿ", "m"],
        ["ṁ", "m"],
        ["ṃ", "m"],
        ["ɱ", "m"],
        ["ᵯ", "m"],
        ["ᶆ", "m"],
        ["ń", "n"],
        ["ň", "n"],
        ["ņ", "n"],
        ["ṋ", "n"],
        ["ȵ", "n"],
        ["ṅ", "n"],
        ["ṇ", "n"],
        ["ǹ", "n"],
        ["ɲ", "n"],
        ["ṉ", "n"],
        ["ƞ", "n"],
        ["ᵰ", "n"],
        ["ᶇ", "n"],
        ["ɳ", "n"],
        ["ñ", "n"],
        ["nj", "nj"],
        ["ó", "o"],
        ["ŏ", "o"],
        ["ǒ", "o"],
        ["ô", "o"],
        ["ố", "o"],
        ["ộ", "o"],
        ["ồ", "o"],
        ["ổ", "o"],
        ["ỗ", "o"],
        ["ö", "o"],
        ["ȫ", "o"],
        ["ȯ", "o"],
        ["ȱ", "o"],
        ["ọ", "o"],
        ["ő", "o"],
        ["ȍ", "o"],
        ["ò", "o"],
        ["ỏ", "o"],
        ["ơ", "o"],
        ["ớ", "o"],
        ["ợ", "o"],
        ["ờ", "o"],
        ["ở", "o"],
        ["ỡ", "o"],
        ["ȏ", "o"],
        ["ꝋ", "o"],
        ["ꝍ", "o"],
        ["ⱺ", "o"],
        ["ō", "o"],
        ["ṓ", "o"],
        ["ṑ", "o"],
        ["ǫ", "o"],
        ["ǭ", "o"],
        ["ø", "o"],
        ["ǿ", "o"],
        ["õ", "o"],
        ["ṍ", "o"],
        ["ṏ", "o"],
        ["ȭ", "o"],
        ["ƣ", "oi"],
        ["ꝏ", "oo"],
        ["ɛ", "e"],
        ["ᶓ", "e"],
        ["ɔ", "o"],
        ["ᶗ", "o"],
        ["ȣ", "ou"],
        ["ṕ", "p"],
        ["ṗ", "p"],
        ["ꝓ", "p"],
        ["ƥ", "p"],
        ["ᵱ", "p"],
        ["ᶈ", "p"],
        ["ꝕ", "p"],
        ["ᵽ", "p"],
        ["ꝑ", "p"],
        ["ꝙ", "q"],
        ["ʠ", "q"],
        ["ɋ", "q"],
        ["ꝗ", "q"],
        ["ŕ", "r"],
        ["ř", "r"],
        ["ŗ", "r"],
        ["ṙ", "r"],
        ["ṛ", "r"],
        ["ṝ", "r"],
        ["ȑ", "r"],
        ["ɾ", "r"],
        ["ᵳ", "r"],
        ["ȓ", "r"],
        ["ṟ", "r"],
        ["ɼ", "r"],
        ["ᵲ", "r"],
        ["ᶉ", "r"],
        ["ɍ", "r"],
        ["ɽ", "r"],
        ["ↄ", "c"],
        ["ꜿ", "c"],
        ["ɘ", "e"],
        ["ɿ", "r"],
        ["ś", "s"],
        ["ṥ", "s"],
        ["š", "s"],
        ["ṧ", "s"],
        ["ş", "s"],
        ["ŝ", "s"],
        ["ș", "s"],
        ["ṡ", "s"],
        ["ṣ", "s"],
        ["ṩ", "s"],
        ["ʂ", "s"],
        ["ᵴ", "s"],
        ["ᶊ", "s"],
        ["ȿ", "s"],
        ["ɡ", "g"],
        ["ᴑ", "o"],
        ["ᴓ", "o"],
        ["ᴝ", "u"],
        ["ť", "t"],
        ["ţ", "t"],
        ["ṱ", "t"],
        ["ț", "t"],
        ["ȶ", "t"],
        ["ẗ", "t"],
        ["ⱦ", "t"],
        ["ṫ", "t"],
        ["ṭ", "t"],
        ["ƭ", "t"],
        ["ṯ", "t"],
        ["ᵵ", "t"],
        ["ƫ", "t"],
        ["ʈ", "t"],
        ["ŧ", "t"],
        ["ᵺ", "th"],
        ["ɐ", "a"],
        ["ᴂ", "ae"],
        ["ǝ", "e"],
        ["ᵷ", "g"],
        ["ɥ", "h"],
        ["ʮ", "h"],
        ["ʯ", "h"],
        ["ᴉ", "i"],
        ["ʞ", "k"],
        ["ꞁ", "l"],
        ["ɯ", "m"],
        ["ɰ", "m"],
        ["ᴔ", "oe"],
        ["ɹ", "r"],
        ["ɻ", "r"],
        ["ɺ", "r"],
        ["ⱹ", "r"],
        ["ʇ", "t"],
        ["ʌ", "v"],
        ["ʍ", "w"],
        ["ʎ", "y"],
        ["ꜩ", "tz"],
        ["ú", "u"],
        ["ŭ", "u"],
        ["ǔ", "u"],
        ["û", "u"],
        ["ṷ", "u"],
        ["ü", "u"],
        ["ǘ", "u"],
        ["ǚ", "u"],
        ["ǜ", "u"],
        ["ǖ", "u"],
        ["ṳ", "u"],
        ["ụ", "u"],
        ["ű", "u"],
        ["ȕ", "u"],
        ["ù", "u"],
        ["ủ", "u"],
        ["ư", "u"],
        ["ứ", "u"],
        ["ự", "u"],
        ["ừ", "u"],
        ["ử", "u"],
        ["ữ", "u"],
        ["ȗ", "u"],
        ["ū", "u"],
        ["ṻ", "u"],
        ["ų", "u"],
        ["ᶙ", "u"],
        ["ů", "u"],
        ["ũ", "u"],
        ["ṹ", "u"],
        ["ṵ", "u"],
        ["ᵫ", "ue"],
        ["ꝸ", "um"],
        ["ⱴ", "v"],
        ["ꝟ", "v"],
        ["ṿ", "v"],
        ["ʋ", "v"],
        ["ᶌ", "v"],
        ["ⱱ", "v"],
        ["ṽ", "v"],
        ["ꝡ", "vy"],
        ["ẃ", "w"],
        ["ŵ", "w"],
        ["ẅ", "w"],
        ["ẇ", "w"],
        ["ẉ", "w"],
        ["ẁ", "w"],
        ["ⱳ", "w"],
        ["ẘ", "w"],
        ["ẍ", "x"],
        ["ẋ", "x"],
        ["ᶍ", "x"],
        ["ý", "y"],
        ["ŷ", "y"],
        ["ÿ", "y"],
        ["ẏ", "y"],
        ["ỵ", "y"],
        ["ỳ", "y"],
        ["ƴ", "y"],
        ["ỷ", "y"],
        ["ỿ", "y"],
        ["ȳ", "y"],
        ["ẙ", "y"],
        ["ɏ", "y"],
        ["ỹ", "y"],
        ["ź", "z"],
        ["ž", "z"],
        ["ẑ", "z"],
        ["ʑ", "z"],
        ["ⱬ", "z"],
        ["ż", "z"],
        ["ẓ", "z"],
        ["ȥ", "z"],
        ["ẕ", "z"],
        ["ᵶ", "z"],
        ["ᶎ", "z"],
        ["ʐ", "z"],
        ["ƶ", "z"],
        ["ɀ", "z"],
        ["ff", "ff"],
        ["ffi", "ffi"],
        ["ffl", "ffl"],
        ["fi", "fi"],
        ["fl", "fl"],
        ["ij", "ij"],
        ["œ", "oe"],
        ["st", "st"],
        ["ₐ", "a"],
        ["ₑ", "e"],
        ["ᵢ", "i"],
        ["ⱼ", "j"],
        ["ₒ", "o"],
        ["ᵣ", "r"],
        ["ᵤ", "u"],
        ["ᵥ", "v"],
        ["ₓ", "x"],
    ]);

«Как удалить все символы, которых нет в отображении» не было вопроса. Кроме того, к настоящему времени я бы, вероятно, использовал Intl.Collatorдля этой задачи - во время вопроса и в среде, которая мне была нужна, потому что это не было вариантом.
Tomalak

Как бы вы использовали Intl.Collatorдля сопоставления нелатинских букв латинским «эквивалентам»?
eddyP23

1
Я бы не стал. Первоначальный вопрос был о правильной сортировке списка строк по определенному языку. Разные языки сортируют строки по-разному, но простые строки JS не обладают необходимыми знаниями, чтобы делать это правильно. Сопоставление символов с диакритическими знаками и форм без диакритических знаков - это обходной путь. При наличии встроенной поддержки сопоставления сопоставление символов становится относительно бесполезной операцией, поскольку оно никогда не может обеспечить точность и скорость сортировки на основе сопоставления.
Tomalak
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.