Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/424.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 排序函数中的递归_Javascript_Arrays_Sorting_Recursion - Fatal编程技术网

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);
}