, но нет, не о алгоритмах сортирования,а о написании функций-компараторов участвующих в сравнении двух элементов Для начала вспомним как применяются такие функции.
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); // Сортировка по количеству детей и по имени
Комментариев нет:
Отправить комментарий