简体   繁体   English

按逗号分隔值对 DOM 元素进行排序

[英]Sort DOM elements by comma-separated values

Given a random sorted list, each with a data-combi attribute (a comma separated list of numbers), I'd like to sort them in the right order给定一个随机排序列表,每个列表都有一个data-combi属性(一个逗号分隔的数字列表),我想以正确的顺序对它们进行排序

<ul class="result">  
  <li data-combi="10,16,24">Combination: 10,16,24</li>
  <li data-combi="8,7,23">Combination: 8,7,23</li>
  <li data-combi="9,16,23">Combination: 9,16,23</li>
  <li data-combi="8,7,24">Combination: 8,7,24</li>  
  <li data-combi="8,16,24">Combination: 8,16,24</li>
  <li data-combi="9,7,23">Combination: 9,7,23</li>
  <li data-combi="10,16,23">Combination: 10,16,23</li>
  <li data-combi="9,7,24">Combination: 9,7,24</li>  
  <li data-combi="9,16,24">Combination: 9,16,24</li>
  <li data-combi="8,16,23">Combination: 8,16,23</li>
  <li data-combi="10,7,23">Combination: 10,7,23</li>
  <li data-combi="10,7,24">Combination: 10,7,24</li>
</ul>

I'm using this code to sort elements but, since data-combi is a string, the sort result is technically right (ie. "10" is sorted before "9", or "16" is sorted before "7") but not the wanted one:我正在使用此代码对元素进行排序,但是,由于data-combi是一个字符串,因此排序结果在技术上是正确的(即“10”在“9”之前排序,或者“16”在“7”之前排序)但是不是想要的:

var $combiUl = $('ul.result');
var $combiLi = $combiUl.children();

$combiLi.sort(function(a,b){
  var an = a.getAttribute('data-combi');
  var bn = b.getAttribute('data-combi');
  return (an > bn) ? 1 : ((an < bn) ? -1 : 0);
});
// deatch variants and re-append in correct order
$combiLi.detach().appendTo($combiUl);

In my ideal world, each comma separated value in the data-combi attribute should be treated as number, not as a string, thus resulting in the following correct sort:在我的理想世界中, data-combi属性中的每个逗号分隔值都应被视为数字,而不是字符串,从而导致以下正确排序:

<ul class="expected">
  <li data-combi="8,7,23">Combination: 8,7,23</li>
  <li data-combi="8,7,24">Combination: 8,7,24</li>
  <li data-combi="8,16,23">Combination: 8,16,23</li>
  <li data-combi="8,16,24">Combination: 8,16,24</li>
  <li data-combi="9,7,23">Combination: 9,7,23</li>
  <li data-combi="9,7,24">Combination: 9,7,24</li>
  <li data-combi="9,16,23">Combination: 9,16,23</li>
  <li data-combi="9,16,24">Combination: 9,16,24</li>
  <li data-combi="10,7,23">Combination: 10,7,23</li>
  <li data-combi="10,7,24">Combination: 10,7,24</li>
  <li data-combi="10,16,23">Combination: 10,16,23</li>
  <li data-combi="10,16,24">Combination: 10,16,24</li>
</ul>

How to achieve this goal?如何实现这个目标? Please consider that I can have longer or shorter comma-separated strings (ie. 10,7,23,12 , or 10,7 ) depending which options the user choose to "mix".请考虑我可以有更长或更短的逗号分隔字符串(即10,7,23,1210,7 ),具体取决于用户选择“混合”的选项。 Anyway, the length of comma-separated string for each row is consistent and does not change (they contains always N comma-separated items; I cannot have one row like 10,7,23 , another like 9,5 and another like 8,2,24,6 )无论如何,每一行的逗号分隔字符串的长度是一致的并且不会改变(它们总是包含 N 逗号分隔的项目;我不能有一行像10,7,23 ,另一行像9,5和另一行像8,2,24,6 )

Please, any idea?请问,有什么想法吗? Here is the snippet showing what's going on这是显示正在发生的事情的片段

 var $combiUl = $('ul.result'); var $combiLi = $combiUl.children(); $combiLi.sort(function(a,b){ var an = a.getAttribute('data-combi'); var bn = b.getAttribute('data-combi'); return (an > bn)? 1: ((an < bn)? -1: 0); }); // deatch variants and re-append in correct order $combiLi.detach().appendTo($combiUl);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <p>the following "li" are sorted by "data-combi" attribute: since this is a string, the sort is technically right, but this is not what I am trying to achieve</p> <ul class="result"> <li data-combi="10,16,24">Combination: 10,16,24</li> <li data-combi="8,7,23">Combination: 8,7,23</li> <li data-combi="9,16,23">Combination: 9,16,23</li> <li data-combi="8,7,24">Combination: 8,7,24</li> <li data-combi="8,16,24">Combination: 8,16,24</li> <li data-combi="9,7,23">Combination: 9,7,23</li> <li data-combi="10,16,23">Combination: 10,16,23</li> <li data-combi="9,7,24">Combination: 9,7,24</li> <li data-combi="9,16,24">Combination: 9,16,24</li> <li data-combi="8,16,23">Combination: 8,16,23</li> <li data-combi="10,7,23">Combination: 10,7,23</li> <li data-combi="10,7,24">Combination: 10,7,24</li> </ul>

Need to split on the commas and convert to numbers.需要以逗号分隔并转换为数字。 The if/else could be cleaned up, but this is the basic idea. if/else 可以清理,但这是基本思想。

 var $combiUl = $('ul.result'); var $combiLi = $combiUl.children(); $combiLi.sort(function(a,b){ var an = a.getAttribute('data-combi').split(',').map(Number); var bn = b.getAttribute('data-combi').split(',').map(Number); var c1 = an[0] - bn[0] var c2 = an[1] - bn[1] var c3 = an[2] - bn[2] if (c1>0) return 1 else if (c1<0) return -1 else if (c2>0) return 1 else if (c2<0) return -1 else if (c3>0) return 1 else if (c3<0) return -1 else return 0 }); // deatch variants and re-append in correct order $combiLi.detach().appendTo($combiUl);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <p>the following "li" are sorted by "data-combi" attribute: since this is a string, the sort is technically right, but this is not what I am trying to achieve</p> <ul class="result"> <li data-combi="10,16,24">Combination: 10,16,24</li> <li data-combi="8,7,23">Combination: 8,7,23</li> <li data-combi="9,16,23">Combination: 9,16,23</li> <li data-combi="8,7,24">Combination: 8,7,24</li> <li data-combi="8,16,24">Combination: 8,16,24</li> <li data-combi="9,7,23">Combination: 9,7,23</li> <li data-combi="10,16,23">Combination: 10,16,23</li> <li data-combi="9,7,24">Combination: 9,7,24</li> <li data-combi="9,16,24">Combination: 9,16,24</li> <li data-combi="8,16,23">Combination: 8,16,23</li> <li data-combi="10,7,23">Combination: 10,7,23</li> <li data-combi="10,7,24">Combination: 10,7,24</li> </ul>

The if/else could be replaced with a loop if/else 可以用循环替换

 var $combiUl = $('ul.result'); var $combiLi = $combiUl.children(); $combiLi.sort(function(a,b){ var an = a.getAttribute('data-combi').split(',').map(Number); var bn = b.getAttribute('data-combi').split(',').map(Number); for (let x in an) { if (an[x] > bn[x]) return 1 if (an[x] < bn[x]) return -1 } return 0 }); // deatch variants and re-append in correct order $combiLi.detach().appendTo($combiUl);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <p>the following "li" are sorted by "data-combi" attribute: since this is a string, the sort is technically right, but this is not what I am trying to achieve</p> <ul class="result"> <li data-combi="10,16,24">Combination: 10,16,24</li> <li data-combi="8,7,23">Combination: 8,7,23</li> <li data-combi="9,16,23">Combination: 9,16,23</li> <li data-combi="8,7,24">Combination: 8,7,24</li> <li data-combi="8,16,24">Combination: 8,16,24</li> <li data-combi="9,7,23">Combination: 9,7,23</li> <li data-combi="10,16,23">Combination: 10,16,23</li> <li data-combi="9,7,24">Combination: 9,7,24</li> <li data-combi="9,16,24">Combination: 9,16,24</li> <li data-combi="8,16,23">Combination: 8,16,23</li> <li data-combi="10,7,23">Combination: 10,7,23</li> <li data-combi="10,7,24">Combination: 10,7,24</li> </ul>

Change the following lines:更改以下行:

$combiLi.sort(function(a,b){
  var an = a.getAttribute('data-combi');
  var bn = b.getAttribute('data-combi');
  return (an > bn) ? 1 : ((an < bn) ? -1 : 0);
});

to this:对此:

$combiLi.sort(function (a, b) {
    let an = a.getAttribute('data-combi').split(",").join("");
    let bn = b.getAttribute('data-combi').split(",").join("");
    return an - bn;
});

You will be able to do it without loops.您将能够在没有循环的情况下做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM