javascript - 表行排序和字符串性能

标签 javascript jquery performance string

我有一个包含大量行的表,不适合分页。此表中的行可以通过单击列标题进行排序,这会触发基于 http://www.exforsys.com/tutorials/jquery/jquery-basic-alphabetical-sorting.html 的客户端排序算法。该函数动态地向每一行添加一个“expando”属性,从而缓存键预排序:

row.sortKey = $(row).children('td').eq(column).text().toUpperCase();

如您所见,属性值只是设置为单击的列的内容,并且在排序完成后它们将被丢弃(为空)。性能实际上出奇的好——但是包含更多文本的列排序似乎更慢。

由于排序只是为了让用户更容易找到他们正在寻找的行,我认为可以通过使用 substr(0,7) 或其他方式裁剪键值来加快速度(八个字符应该提供足够的精度)。但是,我发现执行 substr() 所带来的性能成本比节省的成本要高,而且如果有的话,它会使排序速度变慢。

有谁知道可以应用于此方法的任何(其他)优化?

这是一个更完整的例子:

var rows = $table.find('tbody > tr').get();
$.each(rows, function(index, row) {
    row.sortKey = $(row).children('td').eq(column).text().toUpperCase()
})
rows.sort(function(a, b) {
    if (a.sortKey < b.sortKey) return -1
    if (a.sortKey > b.sortKey) return 1
    return 0
})
$.each(rows, function(index, row) {
    $table.children('tbody').append(row)
    row.sortKey = null
})

编辑:这是我的代码的最终版本,包含以下答案中提供的许多优化:

$('table.sortable').each(function() {
    var $table = $(this);
    var storage = new Array();
    var rows = $table.find('tbody > tr').get();
    $('th', $table).each(function(column) {
        $(this).click(function() {
            var colIndex = this.cellIndex;
            for(i=0;i<rows.length;i++) {
                rows[i].sortKey = $(rows[i].childNodes[colIndex]).text().toUpperCase();
            }
            rows.sort(function(a, b) {
                if (a.sortKey < b.sortKey) return -1;
                if (a.sortKey > b.sortKey) return 1;
                return 0;
            });
            for(i=0;i<rows.length;i++) {
                storage.push(rows[i]);
                rows[i].sortKey = null;
            }
            $table.children('tbody').append(storage);
        });
    });
});

最佳答案

你举的例子有几个问题。第一个问题是您在循环内使用 jquery 选择列。这是一个主要的性能损失。如果您可以控制 html 代码,我建议您使用普通的 DOM 方法来获取您想要排序的所需列。请注意,有时当您可能期望表格单元格节点时,您可能会得到一个文本节点。我稍后再谈。 for 循环速度更快,因此您可以考虑使用它而不是 $.each,但我建议您对其进行基准测试。

我以您的示例创建了一个包含 1000 行的表。在我的机器上花了大约 750 毫秒来排序。我做了一些优化(见下面的代码)并设法将其降低到 200 毫秒。排序本身花费了大约 20 毫秒(不错)。

var sb = [];
sb.push("<table border='1'>");
var x;
for (var i = 0; i < 1000; i++) {
    x = Math.floor(Math.random() * 1000);
    sb.push("<tr><td>data");
    sb.push(x);
    sb.push("</td></tr>");
}
sb.push("</table>");

document.write(sb.join(""));

$table = $("table");
var rows = $table.find('tbody > tr').get();
var columnIndex = 0;

var t = new Date();

$.each(rows, function(index, row) {
    row.sortKey = $(row.childNodes[columnIndex]).text();
});
alert("Sort key: " + (new Date() - t) + "ms");
t = new Date();

rows.sort(function(a, b) {
        return a.sortKey.localeCompare(b.sortKey);
});
alert("Sort: " + (new Date() - t) + "ms");
t = new Date();
var tbody = $table.children('tbody').get(0);

$.each(rows, function(index, row) {
    tbody.appendChild(row);
    delete row.sortKey;
})

alert("Table: " + (new Date() - t) + "ms");

当你为了速度而写作时,你希望每次迭代都尽可能快,所以不要在循环中做你可以在循环外做的事情。例如移动 $table.children('tbody').get(0);在最后一个循环之外大大加快了速度。

至于使用 DOM 方法访问列,您需要的是列索引,因此您可以遍历第 th 列,直到找到正确的列(前提是 th 标签和 td 标签的 html 格式相同)。然后,您可以使用该索引获取正确的行子节点。

此外,如果表是静态的并且用户倾向于对其进行更多排序,则您应该缓存行而不是删除 sortKey 属性。这样您就可以节省大约 30% 的分拣时间。还有表格内容的问题。如果内容是文本,这种排序方式没问题。如果它包含数字等,那么您需要考虑这一点,因为我使用的是 localeCompare,这是一种 String 类型的方法。

关于javascript - 表行排序和字符串性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/730126/

相关文章:

javascript - 更新钩子(Hook)后,DOM 渲染未触发

javascript - 在 Safari for Mac 中使用 Ctrl+Click 时如何禁用上下文菜单事件中的单击事件?

javascript - 有没有办法获取我的 Stack Exchange 统计数据?

performance - SQL Server 2008 空间查询。如果它们彼此相交,如何对多边形进行分组?

java - 从手写持久层迁移到ORM

java - 提高方法性能java

javascript - Three.js - 无法加载纹理

jquery - 如何切换显示 :none, display:block

javascript - 将 jQuery 与小部件捆绑在一起

javascript - jQuery $.ajax 在 IE8 中不工作,但在 FireFox 和 Chrome 中工作