0

编辑:Pete 提供了一个非常好的解决方案,当字段包含数字时有效,但是我也需要能够对字符串进行排序 - 有什么想法吗?

我正在尝试编写一个 javascript 排序算法,该算法将根据单击的列对表进行排序 - 我知道这是半重新发明轮子,但设计太复杂,我无法尝试插入其他插件等。

有些列是文本,有些列是数字。

单击列调用:sort(X,Y)。X 是列号,因此我们知道要比较哪些单元格进行排序。Y 是模式,即升序或降序。

排序函数的代码是:

function sort(field, mode) {
var tabrows = 0;
$(".data tr").each(function() { if($(this).hasClass("hdr")) { } else {tabrows++;} });   
var swapped;
do {
        swapped = false;
        for (var i=0;i< tabrows; i++) {

            var j = i + 3;
            var k = i + 4;  

            var row1 = $(".data tr:nth-child("+j+")");
            var row2 = $(".data tr:nth-child("+k+")");

            var field1 = row1.find("td:eq("+field+")").text();      
            var field2 = row2.find("td:eq("+field+")").text();

            if(shouldswap(field1, field2, mode)) {
                swaprows(row1, row2);
                swapped = true;
            }
        }
    } while (swapped);
}

shouldswap 函数如下:

function shouldswap(field1, field2,mode) {


    if(field1 > field2) {
            if(mode==1) {   
                return true;
            } else {
                return false;
            }   
    }

    return false;

}

swaprows 函数的代码:

function swaprows(row1, row2) {
      row2.insertBefore(row1);
}

谁能明白为什么这会导致浏览器冻结/锁定。我已经为此工作了很长一段时间,所以我认为一双新的眼睛可能会指出一些愚蠢的事情!任何帮助表示赞赏:)

4

2 回答 2

1

问题可能是您多次调用 jQuery 构造函数并对其执行繁重的操作(例如,使用.find()复杂的选择器)。因此,您的功能很慢,这可能就是问题所在。

好消息是 JavaScript 有一个 QuickSort(一种非常快速的排序功能)的本机实现,它可能会满足您的需求。当结合减少昂贵的调用时,您的代码最终应该会变得更加高效。我会将您的代码更改为如下所示:

var sortByField = function(field, mode) {
    var numExp = /^-?\d*\.?\d+$/;
    var $rows = $(".data tr:not(.hdr)"), $table = $(".data");
    $rows.each(function () {
        this.fieldVal = $(this).find("td:eq("+field+")").text();
        if(numExp.test(this.fieldVal)) { //if field is numeric, convert it to a number
            this.fieldVal = +this.fieldVal;
        }
    }).sort(function (a, b) {
        if (mode === 1) {
            return (a.fieldVal > b.fieldVal) ? -1 : 1;    
        }    
        return (a.fieldVal < b.fieldVal) ? -1 : 1;
    }).detach().each(function () {
        $(this).appendTo($table);
    });
};

这不适用于一页上的多个表(因为它假定所有内容都在同一个表上)。所以如果你想这样做,你应该传入表格或表格选择器作为参数。但这很容易解决。你可以在这里看到我的解决方案:

http://jsfiddle.net/r8wtK/(更新)

它应该比您的代码更有效,并且应该减少相当多的“冻结”(甚至完全)。

更新:

OP 指出,某些字段可能包含字符串。对数字进行字符串比较是不好的,因为它会返回字典顺序(例如"10" < "2")。所以我添加了一个测试,在进行排序之前查看数据是否显示为数字。

于 2012-09-12T16:51:14.913 回答
0

可能是i为了获得行索引,您要添加 3 和 4 吗?因此,当i到达时(tabrows-1),它似乎将尝试访问索引为(tabrows+2)and的行(tabrows+3)。如果我正确理解您的逻辑,则这些超出范围,因此, row1,row2将是空的。因此,如果您在 中,我认为这将使您的算法尝试交换这两个不存在的行并继续比较无穷大。这是有道理的,还是我误解了你的逻辑?field1field2mode==1

如果是这种情况,我认为您只需将 for 循环更改为:

for (var i=0;i< tabrows-4; i++) {
     // your code
}

无论如何,将 3 加到 j 和 4 加到 k 的目的是什么?您是否不想比较顶部的 3 行数据?

于 2012-09-12T16:44:24.797 回答