Сортировка многомерного массива в JavaScript с использованием пользовательской функции сортировки

Сортировка многомерного массива в JavaScript. Просмотрел другие сообщения, но не могу понять, как передать элементы массива пользовательской функции сортировки, которая определяет, следует ли сортировать строку или числа. Пользовательская функция сортировки такова:

function colSort(a, b) {
    if (sortDown) dValue = 1
    else dValue = -1;

    if (isNumeric(a[sortIndex])) {
        return (b[sortIndex] - a[sortIndex]) * dValue;
    } else {
        var astring = a[sortIndex].toLowerCase();
        var bstring = b[sortIndex].toLowerCase();
        if (bstring > astring) return -dValue;
        if (bstring < astring) return dValue;
        return 0;
    }
}

Массив выглядит так:

var qbStats =[

   ['David Lea', 'GB', 343, 502, 68.3, 4643, 9.2, 45, 6, 122.5],

   ['Kevin Whyte', 'NO', 440, 622, 70.7, 5087, 8.2, 41, 13, 108.4]

]

Заголовки столбцов в таблице HTML, в которой перечислены элементы массива, должны быть доступны для сортировки по возрастанию/убыванию в выбранном столбце.

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

Я знаю, что это начинается так:

qbStats.sort(colSort(a,b));

Но я не знаю, как передать элементы массива для сортировки по определенному индексу. Пример: как мне сказать ему сортировать 'GB' и 'NO' как 'a' и 'b'? Спасибо за любую помощь, которую вы можете дать!


person user1560289    schedule 24.01.2016    source источник
comment
Непонятно, как именно вы хотите, чтобы массивы были отсортированы. Можете ли вы привести пример с тремя или четырьмя строками и объяснить, как они должны располагаться и почему?   -  person Pointy    schedule 24.01.2016
comment
Подождите - кажется, я понял. Вы хотите упорядочить весь список по значению одного столбца. ХОРОШО.   -  person Pointy    schedule 24.01.2016


Ответы (2)


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

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

function byColumn(sortIndex) {
  return function colSort(a, b) {
    if (sortDown) dValue = 1
    else dValue = -1;

    if (isNumeric(a[sortIndex])) {
      return (b[sortIndex] - a[sortIndex]) * dValue;
    } else {
      var astring = a[sortIndex].toLowerCase();
      var bstring = b[sortIndex].toLowerCase();
      if (bstring > astring) return -dValue;
      if (bstring < astring) return dValue;
      return 0;
    }
  };
}

А потом:

qbStats.sort(byColumn(4)); // sort by column 4

Функция byColumn() — это просто оболочка для вашей функции компаратора. Когда он вызывается, он возвращает реальную функцию, которую будет использовать процесс сортировки. Эта функция имеет доступ к параметру sortIndex, который был передан во время ее создания, поэтому она «знает», как сравнивать две строки.

person Pointy    schedule 24.01.2016
comment
Я думаю, что это может быть немного ближе к тому, что мне нужно, но откуда берутся «а» и «б»? Разве они не являются элементами массива первого измерения? Как же тогда colSort узнает индекс, по которому следует сортировать? Предполагается, что сценарий просто знает, что такое a и b? - person user1560289; 25.01.2016
comment
Параметры a и b исходят из механизма сортировки. Сортировка должна сравнивать пары значений из массива, и для этого она вызывает вашу функцию сравнения с двумя значениями. Вашей функции не нужно беспокоиться о том, какими двумя значениями они являются; ему просто нужно ответить ответом, на который следует прийти первым. - person Pointy; 25.01.2016
comment
Кажется, я начинаю понимать. Что я сделал, так это просто использовал array.sort(colSort); и он сделал то, что вы сказали, он знал, что нужно извлекать значения a и b, поскольку команда sort() повторяла каждый набор сравниваемых элементов. Я сделал это сложнее, чем нужно, но ваш ответ помог мне увидеть решение. - person user1560289; 25.01.2016

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

var qbStats = [['David Lea', 'GB', 343, 502, 68.3, 4643, 9.2, 45, 6, 122.5], ['Kevin Whyte', 'NO', 440, 622, 70.7, 5087, 8.2, 41, 13, 108.4]];

function sort(column, sortOrder, isNumber) {
    if (isNumber) {
        if (~sortOrder) {
            return function (a, b) {
                return a[column] - b[column];
            }
        } else {
            return function (a, b) {
                return b[column] - a[column];
            }
        }
    } else {
        if (~sortOrder) {
            return function (a, b) {
                return a[column].localeCompare(b[column]);
            }
        } else {
            return function (a, b) {
                return b[column].localeCompare(a[column]);
            }
        }
    }
}

qbStats.sort(sort(0, 1, false)); // sort 0th column, ascending by string
document.write('<pre>' + JSON.stringify(qbStats, 0, 4) + '</pre>');

qbStats.sort(sort(2, -1, true)); // sort 2th column, descending by number
document.write('<pre>' + JSON.stringify(qbStats, 0, 4) + '</pre>');

person Nina Scholz    schedule 24.01.2016
comment
Я ценю ваш ответ, но я все еще немного потерян. Функция сортировки завершится динамической сортировкой любого из нескольких массивов, поэтому массивы должны передаваться в функцию сортировки динамически, а индекс, по которому выполняется сортировка, также должен передаваться динамически. Мне также необходимо использовать функцию colSort(), как описано ранее. - person user1560289; 25.01.2016