【问题标题】:More efficient jQuery sort method for DOM elements based on numerical attribute基于数值属性的DOM元素更高效的jQuery排序方法
【发布时间】:2011-05-29 00:39:00
【问题描述】:

我编写了一些简单的 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 进行这种排序的更有效方法是什么?

【问题讨论】:

标签: jquery sorting performance


【解决方案1】:

如果您担心性能,并且确定属性来自哪里,您可以直接使用 DOM 方法,在这种情况下为.getAttribute()

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

You can test the difference here,正如您所见,它不仅仅是一点点速度提升,.attr() 在内部做了很多额外工作,最终在这种情况下最终调用了.getAttribute()

【讨论】:

  • 这仍在检索每个元素的属性。有没有办法让我不必为每次比较获取属性?
  • @Mike - 你可以循环遍历它并将每一个存储在一个对象映射中,是的......但是这样更有效率吗?你必须测试,元素的迭代不是免费的,你必须比较成本......总是测试!
  • @Mike Grace 你刚刚回答了你自己的问题。获取一次属性,将它们存储为 {timestamp, jquery} 数组的一部分,按时间戳排序。
【解决方案2】:

如果您需要重复进行大量排序,最好采用不涉及 jQuery 的更原生的方法。否则,真的不会有太大的影响。

这里有一些测试尝试了几种不同的方法 -> http://jsperf.com/jquery-sort-by-numerical-property/2

【讨论】:

  • 您是指像 Nick Craver 发布的解决方案这样的原生方法吗?
【解决方案3】:

使用jQuery 1.6 Data() 会快很多。

第一:

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

确定您的循环是相同的,但每个循环的处理量要少得多。

【讨论】:

  • 酷!感谢您的回答和解释。
【解决方案4】:

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

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

如果你的时间戳属性真的只是一个数字,我认为它们会产生相同的值。

【讨论】:

【解决方案5】:

如果您的比较函数很昂贵,则标准方法是 schwartzian 变换(在某些 cmets 中看到,但没有实际示例):

  1. 将排序键提取到 [key, object] 对中
  2. 使用提取的键进行排序
  3. 提取原始对象

例子:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2011-01-15
    • 1970-01-01
    • 2023-04-10
    • 2011-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-09
    相关资源
    最近更新 更多