Сортировка и поиск с localeCompare
С задачей обычной сортировки, если речь про английский язык или числа, норм справляется sort() или sort((a, b) => a - b).
Но вот когда сортируются «неанглийские» строки, то тогда пригодится метод localeCompare у строк: sort((a, b) => a.localeCompare(b)), который сравнивает сроки учитывая действующую локаль пользовательской системы. Грубо говоря, где в текущей локали один Unicode-символ находится по сравнению с другим символом – перед ним или после него?
Что интересно, базовый метод появился в браузерах ещё практически с начала существования Chrome, Firefox и Safari. Но позже в него была добавлена поддержка дополнительных параметров, уточняющих как именно нужно сравнивать строки. Причём под капотом localeCompare будет вызывать Intl.Collator API, в браузерах его поддерживающих.
Настройка caseFirst — первыми идёт нижний регистр или верхний:
["Е", "а", "е", "А"] .sort((a, b) => a.localeCompare(b, "ru")) [ // по умолчанию сначала нижний регистр // ["а","А","е","Е"]
("Е", "а", "е", "А") ].sort((a, b) => a.localeCompare(b, "ru", { caseFirst: "upper" }));// теперь сначала идёт верхний регистр// ["А","а","Е","е"]Это актуально и для английских текстов тоже.
Настройка sensitivity — учитывать ли при сравнении регистр и вспомогательные символы вокруг буквы (a и á, е и ё):
"лёд".localeCompare("ЛЕД", "ru", { sensitivity: "variant" }) === 0;// л ≠ д, е ≠ ё, л ≠ Л// false
"лед".localeCompare("лёд", "ru", { sensitivity: "case" }) === 0;// л ≠ д, е = ё, л ≠ Л.// true
"Лёд".localeCompare("лёд", "ru", { sensitivity: "accent" }) === 0;// л ≠ д, е ≠ ё, л = Л// true
"лёд".localeCompare("ЛЕД", "ru", { sensitivity: "base" }) === 0;// л ≠ д, е = ё, л = Л// trueТо есть если пользователь вводит в поиск ЛЕД, можно однозначно определить, что это лёд прямо в браузере.
Настройка numeric — для корректной сортировки строк с числами:
["09", "1", "2", "01", "10"] .sort((a, b) => a.localeCompare(b)) [ // по умолчанию сортируется по символам // ["01","09","1","10","2"]
("09", "1", "2", "01", "10") ].sort((a, b) => a.localeCompare(b, "ru", { numeric: true }));// теперь строки учитываются как числа// ["1","01","2","09","10"]Так можно отсортировать строки с числами без явного приведения к числам.
Что радует, все возможные доп настройки доступны с Chrome 87, FF 85, Safari 14.1, Node 15.