Подготовить массив для сортировки в закрытии

Согласно моим исследованиям и поиску в 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);

... который просто кэширует результат выполнения замыкания, если вам нужно выполнить сортировку несколько раз.

Другие вопросы по тегам