基于数字属性的DOM元素的更有效的jQuery排序方法

时间:2010-12-21 19:07:06

标签: jquery sorting performance

我编写了一些简单的jQuery来根据数字属性对某些元素进行排序,如http://jsfiddle.net/MikeGrace/Vgavb/所示

// get array of elements
var myArray = $("#original div");

// sort based on timestamp attribute
myArray.sort(function (a, b) {

    // convert to integers from strings
    a = parseInt($(a).attr("timestamp"), 10);
    b = parseInt($(b).attr("timestamp"), 10);

    // compare
    if(a > b) {
        return 1;
    } else if(a < b) {
        return -1;
    } else {
        return 0;
    }
});

// put sorted results back on page
$("#results").append(myArray);

它工作正常,但我不认为它会扩展,因为总共有185个jQuery调用,其中184个获取元素的属性来进行比较。

使用jQuery进行排序的更有效方法是什么?

5 个答案:

答案 0 :(得分:6)

如果您担心性能,并确定该属性的来源,您可以直接使用DOM方法,.getAttribute()在这种情况下:

a = parseInt(a.getAttribute("timestamp"), 10);
b = parseInt(b.getAttribute("timestamp"), 10);

You can test the difference here,正如你所看到的那样,速度提升不止一点,.attr()在内部完成额外工作的很多,最终在此调用.getAttribute()本身无论如何。

答案 1 :(得分:4)

如果你需要反复进行大量的排序,那么努力实现一种不涉及jQuery的更原生的方法会更好。否则,实际上没有太多可以产生显着差异。

以下是尝试一些不同方法的一些测试 - &gt; http://jsperf.com/jquery-sort-by-numerical-property/2

答案 2 :(得分:3)

使用jQuery 1.6 Data()会更快。

首先:

  

数据属性在第一次访问数据属性时被拉出,然后不再被访问或变异(所有数据值都在内部存储在jQuery中)。

这意味着在第一个是内部之后访问特定数据值,因此不需要进行DOM查找或解析值。

第二

  

每次尝试都将字符串转换为JavaScript值(包括布尔值,数字,对象,数组和null)。字符串值“100”将转换为数字100。

现在该值在内部存储为数字,不需要每次都进行解析。

HTML

<div id="original">
  <div data-timestamp="99">99</div>
  <div data-timestamp="999">999</div>
  <div data-timestamp="12">12</div>
  <div data-timestamp="11">11</div>
  <div data-timestamp="10">10</div>
  <div data-timestamp="9">9</div>
  <div data-timestamp="8">8</div>
  <div data-timestamp="7">7</div>
  <div data-timestamp="6">6</div>
  <div data-timestamp="5">5</div>
  <div data-timestamp="4">4</div>
  <div data-timestamp="3">3</div>
  <div data-timestamp="2">2</div>
  <div data-timestamp="1">1</div>
  <div data-timestamp="9999">9999</div>
</div>

的Javascript

// sort based on timestamp attribute
myArray.sort(function (a, b) {

    // convert to integers from strings
    a = $(a).data("timestamp");
    b = $(b).data("timestamp");
    count += 2;
    // compare
    if(a > b) {
        return 1;
    } else if(a < b) {
        return -1;
    } else {
        return 0;
    }
});

Update jsFiddle Example

确定你的循环是相同的,但每循环处理的次数要少得多。

答案 3 :(得分:2)

对于它的价值,我认为你不需要调用慢速的parseInt:

a = parseInt($(a).attr("timestamp"), 10);
a = +$(a).attr("timestamp");

如果你的timestamp属性确实只是一个数字,我认为它们会产生相同的值。

答案 4 :(得分:1)

如果你的比较函数很昂贵,那么标准方法就是schwartzian变换(见一些注释,但没有实际例子):

  1. 将排序键提取到[key,object]对
  2. 使用提取的密钥排序
  3. 提取原始对象
  4. 示例:

    Array.prototype.schwartzian_sort = function (key_of) {
       var i;
    
       for (i = 0; i < this.length; ++i)
          this[i] = [key_of (this[i]), this[i]];
    
       this.sort (function (a, b) {
          a = a[0];
          b = b[0];
    
          return a < b ? -1
               : a > b ?  1
               :          0;
       });
    
       for (i = 0; i < this.length; ++i)
          this[i] = this[i][1];
    
       return this;
    }
    

    而不是比较函数,您传递一个提取srings或数字的函数:

    myArray.sort(function (e) {
       return parseInt ($(a).attr ("timestamp"), 10);
    });
    

    每个元素只调用一次parseInt和attr,它总是比在比较函数中调用时少。

相关问题