2009-04-08 55 views
4

我有一个表中有大量不适合分页的行。表行排序和字符串性能

row.sortKey = $(row).children('td').eq(column).text().toUpperCase(); 
:本表中的行可以通过点击列标题触发基于 http://www.exforsys.com/tutorials/jquery/jquery-basic-alphabetical-sorting.html客户机侧排序algoritm的函数动态地增加了一个“的expando”属性的每一行,从而高速缓存密钥预排序进行排序

正如您所看到的,属性值只是设置为被点击的列的内容,并且一旦排序完成,它们将被丢弃(空值)。性能实际上非常好 - 但包含更多文本的列似乎排序较慢。

由于排序只是为了让用户更容易找到他们正在查找的行,我认为通过用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); 
     }); 
    }); 
}); 

回答

2

一个优化就是修改这个代码:

$.each(rows, function(index, row) { 
     $table.children('tbody').append(row) 
     row.sortKey = null 
}) 

来,而不是在一个时间追加一行,追加更大的块,或者所有可能的话。要做到这一点,你需要首先创建一个所有行的字符串,然后一次追加。

使用的Array.push和array.join到Concat的字符串

+0

这听起来像一个好主意,会有一个去看看我能想出什么! – 2009-04-08 14:47:02

-4

Tjena奥拉!

这可能与您的问题没有关系,但我们讨论了多少行?对于非常大量的行 - 成千上万的表格非常缓慢。更轻量级的解决方案是使用div和css来模拟表格。它可能不是语义上的正确(哈希表和语义在同一个短语中,谁会想到?),但速度更快。我能想到的

+0

通常不会超过几百行(按<0.5s排序),最大值约为1500(按~4s排序)。是的,有趣的是,这是

真正意义上的100%的情况之一! – 2009-04-08 14:07:41

+0

使用数据表没有什么问题,这就是为什么他们在那里。实际上,它们是用于在表格中显示数据的语义合适的解决方案。所有表格都不错! – cgp 2009-04-08 14:15:14

+0

我同意!在九十年代从基于桌面的Photoshop“切片”,到在新千年完全基于CSS的语义正确的弹性,我现在抓住每一个机会在适当的时候使用

。还有,等都是摇滚! – 2009-04-08 14:23:23

0

继mkoryak的建议,我现在已经修改了代码装配中的行数组,然后添加他们都一气呵成:

$.each(rows, function(index, row) { 
    storage.push(row); 
    row.sortKey = null; 
}); 
$table.children('tbody').append(storage); 

这似乎有改进的表现约25% - 排序1500行现在需要约3秒,而不是以前的约4秒。

5

有几个问题你给的例子。第一个问题是你在循环中使用jQuery来选择列。这是一个主要的表现惩罚。如果你对HTML代码有任何控制权,我建议你使用普通的DOM方法来获得你想要排序的所需列。请注意,有时您可能会希望有一个表格单元节点,您可能会得到一个文本节点。我会在稍后回顾。 for循环速度更快,所以您可以考虑使用它来代替$ .each,但我建议您对其进行基准测试。

我把你的例子,并创建了1000行的表。我的机器花了大约750毫秒对它进行分类。我做了一些优化(见下面的代码),并设法将其降至200毫秒。排序本身需要大约20ms(不错)。

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列,直到找到正确的一列为止(假设html标签对于th标签和td标签是相同的) 。然后您可以使用该索引来获取正确的行子节点。另外,如果表格是静态的,并且用户可能对其进行更多排序,则应该缓存行并且不要删除sortKey属性。那么你可以节省大约30%的排序时间。还有表格内容的问题。如果内容是文本,则此排序方法很好。如果它包含数字等,那么你需要考虑一下,因为我使用的是localeCompare,它是String类的一种方法。

0

我正在使用DataTables jQuery plugin进行这种工作,而我之前使用YUI DataTable组件。 1.5 beta版本的jQuery DataTables组件包括从html代码实例化,或者使用AJAX数据源。安装非常简单,而且对数据进行筛选和分类非常快捷。

我发现有一次,我打了大约1600条线,我的相当详细,唯一的办法是与服务器端数据加载。

,