, но нет, не о алгоритмах сортирования,а о написании функций-компараторов участвующих в сравнении двух элементов Для начала вспомним как применяются такие функции.
var arr = [1,5,7,3,2]; //обычная сортировка arr.sort(); //[1, 2, 3, 5, 7] //сортировка с применение функции-компаратора function myCompar (a, b){ if (a > b) { return -1; } else if (a < b) { return 1; } else { return 0; } }; arr.sort(myCompar); //[7, 5, 3, 2, 1]С приведенного выше примера видно что функция-компаратор ни что иное как: функция принимающая сравниваемые элементы в виде двух аргументов и возвращает результат их сравнения (1, -1, 0). В примере я использовал функцию-компаратор для реализации обратной сортировки числового массива, на практике же она чаще используется для сортировки массива объектов (хэшей) или для применения перед сравнением к элементам дополнительных преобразований (parseInt(a, 10), a.toLowerCase()... ). Написание функций-компараторов для сложных типов данных может занять много времени и места в вашем коде и зачастую такие сортировки нечитабельные Давайте попробуем оптимизировать и упростить данный процесс. За основу был взят код Triptych'a, после чего он был изменен и оброс рюшечками :).
function get_sorter_by (field, reverse, primer) { if (field && field.constructor == Array) { var sorters = []; for (var i = 0; i < field.length; i += 1) { sorters.push(get_sorter_by(field[i][0], field[i][1], field[i][2])); }; return function (a, b) { var res = 0; for (var i = 0; i < sorters.length; i += 1) { res = sorters[i](a, b); if (res != 0) break; }; return res; } } var key; if (field) { key = primer ? function (o) {return primer(o[field])} : function (o) {return o[field]}; } else { key = primer ? function (o) {return primer(o)} : function (o) {return o}; } return function (a, b) { var A = key(a), B = key(b); return ( A < B ? +1 : (A > B ? -1 : 0)) * [-1,1][+!!reverse]; } };Итак, функция get_sorter_by принимает 3 параметра :
- field
- Поле по которому будет проводится сравнение.
- reverse
- Признак "обратной сортировки".
- primer
- Функция для предварительной обработки сортируемых полей.
function get_sorter_by (field, reverse, primer) { if (field && field.constructor == Array) { var sorters = []; for (var i = 0; i < field.length; i += 1) { sorters.push(get_sorter_by(field[i][0], field[i][1], field[i][2])); }; return function (a, b) { var res = 0; for (var i = 0; i < sorters.length; i += 1) { res = sorters[i](a, b); if (res != 0) break; }; return res; } } var key; if (field) { key = primer ? function (o) {return primer(o[field])} : function (o) {return o[field]}; } else { key = primer ? function (o) {return primer(o)} : function (o) {return o}; } return function (a, b) { var A = key(a), B = key(b); return ( A < B ? +1 : (A > B ? -1 : 0)) * [-1,1][+!!reverse]; } }; var arr = [ {name : 'Joe', weight : 100, kids : 1}, {name : 'Hloe', weight : 57, kids : 2}, {name : 'Molly', weight : 53, kids : 0}, {name : 'Shon', weight : 73, kids : 1} ]; function toLowerCase (s){return s.toLowerCase()}; var mySorts = { name_asc : get_sorter_by('name', 0, toLowerCase), name_desc : get_sorter_by('name', 1, toLowerCase), weight60_asc : get_sorter_by('weight', 0, function (w) {return Math.abs(w-60);}), weight60_desc : get_sorter_by('weight', 1, function (w) {return Math.abs(w-60);}), kids_asc : get_sorter_by([ ['kids', 0], ['name', 0, toLowerCase] ]), kids_desc : get_sorter_by([ ['kids', 1], ['name', 0, toLowerCase] ]) }; arr.sort(mySorts.name_asc); // Сортировка по имени arr.sort(mySorts.weight60_desc); // Сортировка по приближенности веса к 60 в обратном порядке arr.sort(mySorts.kids_asc); // Сортировка по количеству детей и по имени
Комментариев нет:
Отправить комментарий