Подготовить массив для сортировки в закрытии
Согласно моим исследованиям и поиску в Google, Javascript, похоже, не поддерживает сортировку с учетом локали и сравнение строк. Есть localeCompare()
, но сообщалось о специфических различиях браузера и невозможности явно указать, какой языковой стандарт используется (языковой стандарт ОС не всегда тот, который требуется). Есть некоторые намерения добавить поддержку сортировки в ECMAScript, но перед этим мы сами по себе. И в зависимости от того, насколько стабильны результаты в разных браузерах, мы можем быть сами по себе навсегда:(.
У меня есть следующий код, который делает алфавитный вид массива. Он ориентирован на скорость, а идеи получены с /questions/2294496/effektivno-zamenit-vse-aktsentirovannyie-simvolyi-v-stroke/2294512#2294512, в который я внес некоторые улучшения скорости.
В этом примере массив слов имеет 13 членов, а функция сортировки вызывается 34 раза. Я хочу заменить некоторые буквы в массиве слов (вам не нужно знать, какие замены сделаны, потому что это не главное в этом вопросе). Если я сделаю эти замены в функции сортировки (тот, который начинается с return function(a, b)
), код неэффективен, поскольку замены выполняются более одного раза для каждого элемента массива. Конечно, я могу сделать эти замены за пределами этого закрытия, я имею в виду перед линией words.sort(sortbyalphabet_timo);
, но это не то, что я хочу.
Вопрос 1: возможно ли изменить массив слов между строками "НАЧАЛО ПОДГОТОВКИ" и "КОНЕЦ ПОДГОТОВКИ", чтобы функция сортировки использовала измененный массив слов?
Вопрос 2: Можно ли ввести аргументы в замыкание, чтобы их мог использовать код между НАЧАЛЬНЫМИ ПОДГОТОВКАМИ и КОНЦАМИ ПОДГОТОВКИ? Я попробовал это без успеха:
var caseinsensitive = true;
words.sort( sortbyalphabet_timo(caseinsensitive) );
И вот, наконец, пример кода, и готовый к запуску пример находится в http://jsfiddle.net/3E7wb/:
var sortbyalphabet_timo = (function() {
// PREPARATION STARTS
var i, alphabet = "-0123456789AaÀàÁáÂâÃãÄäBbCcÇçDdEeÈèÉéÊêËëFfGgHhIiÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöPpQqRrSsTtUuÙùÚúÛûÜüVvWwXxYyÝýŸÿZz",
index = {};
i = alphabet.length;
while (i--) index[alphabet.charCodeAt(i)] = i;
// PREPARATION ENDS
return function(a, b) {
var i, len, diff;
if (typeof a === "string" && typeof b === "string") {
(a.length > b.length) ? len = a.length : len = b.length;
for (i = 0; i < len; i++) {
diff = index[a.charCodeAt(i)] - index[b.charCodeAt(i)];
if (diff !== 0) {
return diff;
}
}
// sort the shorter first
return a.length - b.length;
} else {
return 0;
}
};
})();
var words = ['tauschen', '66', '55', '33', 'täuschen', 'andern', 'ändern', 'Ast', 'Äste', 'dosen', 'dösen', 'Donaudam-0', 'Donaudam-1'];
$('#orig').html(words.toString());
words.sort(sortbyalphabet_timo);
$('#sorted').html(words.toString());`
1 ответ
Можно ли изменить массив слов между строками "НАЧАЛО ПОДГОТОВКИ" и "КОНЕЦ ПОДГОТОВКИ", чтобы функция сортировки использовала измененный массив слов?
Нет, не совсем. У вас нет доступа к самому массиву, ваша функция создает только функцию сравнения, которая позже используется, когда .sort
вызывается в массиве. Если вам нужно изменить массив, вам нужно написать функцию, которая получает его в качестве аргумента; например, вы можете добавить метод на Array.prototype
, Это будет выглядеть
function mysort(arr) {
// Preparation
// declaration of compare function
// OR execution of closure to get the compare function
arr.sort(comparefn);
return arr;
}
Можно ли ввести аргументы в замыкание, чтобы их мог использовать код между НАЧАЛЬНЫМИ ПОДГОТОВКАМИ и КОНЦАМИ ПОДГОТОВКИ?
Да, конечно - это причина использования замыканий:-) Однако вы не можете использовать sortbyalphabet_timo(caseinsensitive)
с вашим текущим кодом. Закрытие, которое у вас есть, немедленно вызывается (называется IIFE) и возвращает функцию сравнения, которую вы передаете в sort, как в вашей демонстрации.
Если ты хочешь sortbyalphabet_timo
чтобы быть замыканием, а не результатом, вы должны убрать скобки после него. Вы также можете использовать аргументы, которые доступны во всей области замыкания (включая функцию сравнения):
var sortbyalphabet_timo_closure = function(caseinsensitive) {
// Preparation, potentially using the arguments
// Declaration of compare function, potentially using the arguments
return comparefn;
}
// then use
words.sort(sortbyalphabet_timo_closure(true));
В настоящее время вы делаете это:
var sortbyalphabet_timo_closure = function(/*having no arguments*/) {
// Preparation, potentially using the arguments
// Declaration of compare function, potentially using the arguments
return comparefn;
}
var sortbyalphabet_timo = sortbyalphabet_timo_closure();
// then use
words.sort(sortbyalphabet_timo);
... который просто кэширует результат выполнения замыкания, если вам нужно выполнить сортировку несколько раз.