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

时间:2022-10-17 23:54:38

I have some simple jQuery written to sort some elements based on a numerical attribute as illustrated at http://jsfiddle.net/MikeGrace/Vgavb/

我有一些简单的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);

It works fine but I don't think it will scale because a total of 185 jQuery calls are made, 184 of them which are getting the attribute of an element to do the comparison.

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

What is a more efficient way to do this sorting with jQuery?

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

5 个解决方案

#1


6  

If you're worried about performance, and know for sure where the attribute comes from, you can use the DOM methods directly, .getAttribute() in this case:

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

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

You can test the difference here, as you see it's more than a little speed boost, .attr() does a lot of extra work internally, ultimately calling .getAttribute() itself in this case anyway.

你可以在这里测试差异,因为你看到它不仅仅是一点速度提升,.attr()在内部完成了很多额外的工作,最终在这种情况下最终调用.getAttribute()本身。

#2


4  

If you need to do lots of sorting repeatedly, it would be good to work towards a more native approach that doesn't involve jQuery. Otherwise, there really isn't much that is going to make a noticeable difference.

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

Here are some tests trying a few different approaches -> http://jsperf.com/jquery-sort-by-numerical-property/2

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

#3


3  

Using jQuery 1.6 Data() will be much faster.

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

First:

第一:

The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery).

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

This means accessing the specific data value after the first is internal so no DOM lookup nor parsing of the value needs to be done.

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

Second:

第二:

Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null). The string value "100" is converted to the number 100.

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

Now that the value is stored internally as a number, it does not need to be parsed every time either.

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

Html

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

使用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

更新jsFiddle示例

Sure your loops are the same, but much less processing per loop.

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

#4


2  

For what it's worth, I don't think you need to call the slow parseInt:

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

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

If your timestamp attribute really is just a number, I think these will yield the same value.

如果你的timestamp属性只是一个数字,我认为这些将产生相同的值。

#5


1  

If your comparison function is expensive, the standard method is the schwartzian transform (seen in some comments, but without an actual example):

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

  1. extract the sort keys into [key, object] pairs
  2. 将排序键提取到[key,object]对中
  3. sort by using the extracted keys
  4. 使用提取的键排序
  5. extract the original objects
  6. 提取原始对象

Example:

例:

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

Instead of a comparison function, you pass a function that extracts srings or numbers:

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

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

This calls the parseInt and attr only once per element, which is always less than if called in a comparison function.

这样每个元素只调用一次parseInt和attr,这比在比较函数中调用时要小。

#1


6  

If you're worried about performance, and know for sure where the attribute comes from, you can use the DOM methods directly, .getAttribute() in this case:

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

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

You can test the difference here, as you see it's more than a little speed boost, .attr() does a lot of extra work internally, ultimately calling .getAttribute() itself in this case anyway.

你可以在这里测试差异,因为你看到它不仅仅是一点速度提升,.attr()在内部完成了很多额外的工作,最终在这种情况下最终调用.getAttribute()本身。

#2


4  

If you need to do lots of sorting repeatedly, it would be good to work towards a more native approach that doesn't involve jQuery. Otherwise, there really isn't much that is going to make a noticeable difference.

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

Here are some tests trying a few different approaches -> http://jsperf.com/jquery-sort-by-numerical-property/2

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

#3


3  

Using jQuery 1.6 Data() will be much faster.

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

First:

第一:

The data- attributes are pulled in the first time the data property is accessed and then are no longer accessed or mutated (all data values are then stored internally in jQuery).

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

This means accessing the specific data value after the first is internal so no DOM lookup nor parsing of the value needs to be done.

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

Second:

第二:

Every attempt is made to convert the string to a JavaScript value (this includes booleans, numbers, objects, arrays, and null). The string value "100" is converted to the number 100.

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

Now that the value is stored internally as a number, it does not need to be parsed every time either.

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

Html

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

使用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

更新jsFiddle示例

Sure your loops are the same, but much less processing per loop.

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

#4


2  

For what it's worth, I don't think you need to call the slow parseInt:

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

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

If your timestamp attribute really is just a number, I think these will yield the same value.

如果你的timestamp属性只是一个数字,我认为这些将产生相同的值。

#5


1  

If your comparison function is expensive, the standard method is the schwartzian transform (seen in some comments, but without an actual example):

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

  1. extract the sort keys into [key, object] pairs
  2. 将排序键提取到[key,object]对中
  3. sort by using the extracted keys
  4. 使用提取的键排序
  5. extract the original objects
  6. 提取原始对象

Example:

例:

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

Instead of a comparison function, you pass a function that extracts srings or numbers:

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

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

This calls the parseInt and attr only once per element, which is always less than if called in a comparison function.

这样每个元素只调用一次parseInt和attr,这比在比较函数中调用时要小。