Javascript 排序函数中的递归
我有一个巨大的比较函数,我用它来对一个二维数组进行数字和字符串排序,我想把它缩小。我已经在彼此内部重复使用了相同的代码块,我认为这是多余的。我认为我可以使用递归使代码更小,但我认为我以前没有这样做过,而且我的排序函数看起来非常复杂。内容如下:Javascript 排序函数中的递归,javascript,arrays,sorting,recursion,Javascript,Arrays,Sorting,Recursion,我有一个巨大的比较函数,我用它来对一个二维数组进行数字和字符串排序,我想把它缩小。我已经在彼此内部重复使用了相同的代码块,我认为这是多余的。我认为我可以使用递归使代码更小,但我认为我以前没有这样做过,而且我的排序函数看起来非常复杂。内容如下: check if a & b is array check if a & b is number or string if number check if a equals to b repe
check if a & b is array
check if a & b is number or string
if number
check if a equals to b
repeat same process with different index
if string
check if a equals to b
repeat same process with different index
示例阵列:
var artists = [
["Katy Perry", "3", "9" ],
["Enrique Iglesias", "3", "9" ],
["Taylor Swift", "2", "9" ],
["Evanescence", "4", "10" ],
["Bruno Mars", "1", "5" ],
["Shania Twain", "3", "12" ],
["Amanda Abizaid", "2", "2" ],
["Death Cab For Cutie", "2", "2" ],
["Simple Plan", "1", "2" ],
];
// sort and prioritize columns by 2, 1, 0, sort order for each 1 = asc
artists.sort(compare.bind([2, 1, 0], [1, 1, 1]));
排序后的相同数组:
var artists = [
["Simple Plan", "1", "2" ],
["Amanda Abizaid", "2", "2" ],
["Death Cab For Cutie", "2", "2" ],
["Bruno Mars", "1", "5" ],
["Taylor Swift", "2", "9" ],
["Enrique Iglesias", "3", "9" ],
["Katy Perry", "3", "9" ],
["Evanescence", "4", "10" ],
["Shania Twain", "3", "12" ],
];
实际比较功能:
// compare is passed to Array.prototype.sort
// array2bSorted.sort(sortable.compare.bind([cols, orders]));
compare : function(a, b) {
var columns = sortable.explodeInnerArrays(this[0]);
var orders = sortable.explodeInnerArrays(this[1]);
var primaryA = a[columns[0]];
var primaryB = b[columns[0]];
if (primaryA instanceof Array) {
primaryA = a[columns[0]][0];
}
if (primaryB instanceof Array) {
primaryB = b[columns[0]][0];
}
switch (sortable.checkDataType(primaryA)) {
case "number":
if (primaryA == primaryB && columns.length > 1) {
var secondaryA = a[columns[1]];
var secondaryB = b[columns[1]];
if (secondaryA instanceof Array) {
secondaryA = a[columns[1]][0];
}
if (secondaryB instanceof Array) {
secondaryB = b[columns[1]][0];
}
switch (sortable.checkDataType(secondaryA)) {
case "number":
if (secondaryA == secondaryB && columns.length > 2) {
var tertiaryA = a[columns[2]];
var tertiaryB = b[columns[2]];
if (tertiaryA instanceof Array) {
tertiaryA = a[columns[2]][0];
}
if (tertiaryB instanceof Array) {
tertiaryB = b[columns[2]][0];
}
switch (sortable.checkDataType(tertiaryA)) {
case "number":
return (tertiaryA - tertiaryB) * orders[2];
break;
case "string":
tertiaryA = sortable.removePunctuation(tertiaryA);
tertiaryB = sortable.removePunctuation(tertiaryB);
if (tertiaryA < tertiaryB) {
return -1 * orders[2];
}
if (tertiaryA > tertiaryB) {
return 1 * orders[2];
}
return 0;
break;
}
}
return (secondaryA - secondaryB) * orders[1];
break;
case "string":
if (secondaryA == secondaryB && columns.length > 2) {
var tertiaryA = a[columns[2]];
var tertiaryB = b[columns[2]];
if (tertiaryA instanceof Array) {
tertiaryA = a[columns[2]][0];
}
if (tertiaryB instanceof Array) {
tertiaryB = b[columns[2]][0];
}
switch (sortable.checkDataType(tertiaryA)) {
case "number":
return (tertiaryA - tertiaryB) * orders[2];
break;
case "string":
tertiaryA = sortable.removePunctuation(tertiaryA);
tertiaryB = sortable.removePunctuation(tertiaryB);
if (tertiaryA < tertiaryB) {
return -1 * orders[2];
}
if (tertiaryA > tertiaryB) {
return 1 * orders[2];
}
return 0;
break;
}
}
secondaryA = sortable.removePunctuation(secondaryA);
secondaryB = sortable.removePunctuation(secondaryB);
if (secondaryA < secondaryB) {
return -1 * orders[1];
}
if (secondaryA > secondaryB) {
return 1 * orders[1];
}
break;
}
}
return (primaryA - primaryB) * orders[0];
break;
case "string":
if (primaryA == primaryB && columns.length > 1) {
var secondaryA = a[columns[1]];
var secondaryB = b[columns[1]];
if (secondaryA instanceof Array) {
secondaryA = a[columns[1]][0];
}
if (secondaryB instanceof Array) {
secondaryB = b[columns[1]][0];
}
switch (sortable.checkDataType(secondaryA)) {
case "number":
if (secondaryA == secondaryB) {
var tertiaryA = a[columns[2]];
var tertiaryB = b[columns[2]];
if (tertiaryA instanceof Array) {
tertiaryA = a[columns[2]][0];
}
if (tertiaryB instanceof Array) {
tertiaryB = b[columns[2]][0];
}
switch (sortable.checkDataType(tertiaryA)) {
case "number":
return (tertiaryA - tertiaryB) * orders[2];
break;
case "string":
tertiaryA = sortable.removePunctuation(tertiaryA);
tertiaryB = sortable.removePunctuation(tertiaryB);
if (tertiaryA < tertiaryB) {
return -1 * orders[2];
}
if (tertiaryA > tertiaryB) {
return 1 * orders[2];
}
return 0;
break;
}
}
return (secondaryA - secondaryB) * orders[1];
break;
case "string":
if (secondaryA == secondaryB && columns.length > 2) {
var tertiaryA = a[columns[2]];
var tertiaryB = b[columns[2]];
if (tertiaryA instanceof Array) {
tertiaryA = a[columns[2]][0];
}
if (tertiaryB instanceof Array) {
tertiaryB = b[columns[2]][0];
}
switch (sortable.checkDataType(tertiaryA)) {
case "number":
return (tertiaryA - tertiaryB) * order;
break;
case "string":
tertiaryA = sortable.removePunctuation(tertiaryA);
tertiaryB = sortable.removePunctuation(tertiaryB);
if (tertiaryA < tertiaryB) {
return -1 * orders[2];
}
if (tertiaryA > tertiaryB) {
return 1 * orders[2];
}
return 0;
break;
}
}
secondaryA = sortable.removePunctuation(secondaryA);
secondaryB = sortable.removePunctuation(secondaryB);
if (secondaryA < secondaryB) {
return -1 * orders[1];
}
if (secondaryA > secondaryB) {
return 1 * orders[1];
}
break;
}
}
primaryA = sortable.removePunctuation(primaryA);
primaryB = sortable.removePunctuation(primaryB);
if (primaryA < primaryB) {
return -1 * orders[0];
}
if (primaryA > primaryB) {
return 1 * orders[0];
}
break;
}
},
Compare函数按多列对数组进行排序,每列都有自己的排序顺序。由于列是在数组中传递的,所以初始索引具有更高的优先级
使用递归,我产生了以下代码,但它不起作用。数组未排序。它也不会抛出任何错误。我删除了一些不相关的部分,使它看起来更简单
我错过了什么
我在if和switch语句中多次使用了相同的代码块,我认为这是多余的
在尝试跳转到递归之前,首先尝试重构:首先使用将重复代码移动到它自己的函数。我设法解决了这个问题,并创建了我的第一个递归 简单地在compare中调用循环函数不会做任何事情,因为它返回1或-1来比较函数,而compare函数不会返回任何东西。我需要返回循环函数返回的值。返回loopa,b,index就成功了
compare : function(a, b) {
var columns = sortable.explodeInnerArrays(this[0]);
var orders = sortable.explodeInnerArrays(this[1]);
function loop(a, b, index) {
var currentA = a[columns[index]];
var currentB = b[columns[index]];
if (currentA instanceof Array) {
currentA = a[columns[index]][0];
}
if (currentB instanceof Array) {
currentB = b[columns[index]][0];
}
switch (sortable.checkDataType(currentA)) {
case "number":
if (currentA == currentB) {
return loop(a, b, (index+1));
}
return (currentA - currentB) * orders[index];
break;
case "string":
if (currentA == currentB) {
return loop(a, b, (index+1));
}
currentA = sortable.removePunctuation(currentA);
currentB = sortable.removePunctuation(currentB)
if (currentA < currentB) {
return -1 * orders[index];
}
if (currentA > currentB) {
return 1 * orders[index];
}
break;
}
}
return loop(a, b, 0);
}
当然可以。递归或循环。无论如何,您都需要这个来支持3个以上的列。你试过了吗?@Bergi是的,还在努力。尝试递归。我不知道如何使用循环。如果这不仅仅是出于教育目的,为什么不使用Array.prototype.sort方法呢?IE>=5.5支持这一点,当然,所有现代web浏览器都支持这一点@雅各布:我正在用数字和字符串值对二维数组进行排序,所以我需要向排序方法传递一个自定义函数。@akinuri,我明白了。现在我理解了用例,我将重新评估。
compare : function(a, b) {
var columns = sortable.explodeInnerArrays(this[0]);
var orders = sortable.explodeInnerArrays(this[1]);
function loop(a, b, index) {
var currentA = a[columns[index]];
var currentB = b[columns[index]];
if (currentA instanceof Array) {
currentA = a[columns[index]][0];
}
if (currentB instanceof Array) {
currentB = b[columns[index]][0];
}
switch (sortable.checkDataType(currentA)) {
case "number":
if (currentA == currentB) {
return loop(a, b, (index+1));
}
return (currentA - currentB) * orders[index];
break;
case "string":
if (currentA == currentB) {
return loop(a, b, (index+1));
}
currentA = sortable.removePunctuation(currentA);
currentB = sortable.removePunctuation(currentB)
if (currentA < currentB) {
return -1 * orders[index];
}
if (currentA > currentB) {
return 1 * orders[index];
}
break;
}
}
return loop(a, b, 0);
}