如何使用jQuery按字母顺序对列表进行排序?


Answers:


106

不会需要jQuery来做到这一点...

function sortUnorderedList(ul, sortDescending) {
  if(typeof ul == "string")
    ul = document.getElementById(ul);

  // Idiot-proof, remove if you want
  if(!ul) {
    alert("The UL object is null!");
    return;
  }

  // Get the list items and setup an array for sorting
  var lis = ul.getElementsByTagName("LI");
  var vals = [];

  // Populate the array
  for(var i = 0, l = lis.length; i < l; i++)
    vals.push(lis[i].innerHTML);

  // Sort it
  vals.sort();

  // Sometimes you gotta DESC
  if(sortDescending)
    vals.reverse();

  // Change the list on the page
  for(var i = 0, l = lis.length; i < l; i++)
    lis[i].innerHTML = vals[i];
}

易于使用...

sortUnorderedList("ID_OF_LIST");

现场演示→


29
我发现这种方法的一个问题是,由于只是移动文本,因此如果在排序之前使用jQuery.data将数据与DOM节点关联,则这些关联现在指向排序后的错误节点。
Rudism

13
使用innerHTML移动元素是一个不好的解决方案,因为排序后它们与元素是不同的。所有对元素的现有引用都将丢失。受JavaScript绑定的所有事件侦听器都将丢失。最好存储元素而不是innerHTML,使用排序函数(vals.sort(function(a,b){return b.innerHTML <a.innerHTML;}))和appendChild来移动元素。
gregers 2012年

3
Buhuuu innerHTML!不要用那个 它是Microsoft专有的东西,从未被W3C认可。
史蒂夫·K

13
恕我直言,这是一个可怕的答案。完全有可能重新排列DOM节点,而无需对其进行序列化和反序列化,也无需破坏任何附加的属性和/或事件。
Alnitak

3
...但是如果您要使用jQuery,您将如何做?
马修

332

像这样:

var mylist = $('#myUL');
var listitems = mylist.children('li').get();
listitems.sort(function(a, b) {
   return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
})
$.each(listitems, function(idx, itm) { mylist.append(itm); });

在此页面上:http : //www.onemoretake.com/2009/02/25/sorting-elements-with-jquery/

上面的代码将对ID为“ myUL”的无序列表进行排序。

或者,您可以使用TinySort之类的插件。https://github.com/Sjeiti/TinySort


6
可以将最后一行替换为$(listitems).appendTo(mylist); ?
阿米尔2010年

26
HL Menken的语录描述了该解决方案:“对于每个问题,都有一个简单,优雅和错误的解决方案。” 该过程运行时间为O(n ^ 2)。相对较短的列表并不明显,但是在包含100个以上元素的列表上,需要3-4秒才能完成排序。
内森·斯特朗

5
@Nathan:关于“对于每个问题,都有一个简单,优雅和错误的解决方案。” -好的,错误的解决方案并不完美。
约翰·菲利普·斯特拉特豪森,2011年

18
某些东西可以优雅而有趣,但仍然会失败。优雅并不意味着成功。
Jane Panda

13
这个解决方案没有错。它回答了这个问题。OP没有指定他需要对100多个项目的列表进行排序。如果他的清单永远不会超过100个项目,则此解决方案是完全可以接受的。+1表示解决方案很慢,-1表示声明满足要求的解决方案为“错误”。
武士灵魂

94
$(".list li").sort(asc_sort).appendTo('.list');
//$("#debug").text("Output:");
// accending sort
function asc_sort(a, b){
    return ($(b).text()) < ($(a).text()) ? 1 : -1;    
}

// decending sort
function dec_sort(a, b){
    return ($(b).text()) > ($(a).text()) ? 1 : -1;    
}

现场演示:http : //jsbin.com/eculis/876/edit


15
这是最好的答案。我在一个甚至喜欢它一行是这样的:$(".list li").sort(function(a, b){return ($(b).text()) < ($(a).text());}).appendTo('.list');。此言一但:.text()应该是.text().toUpperCase()
朱尔斯·科尔

不幸的是,此解决方案在IE中不起作用,而下面的PatrickHecks回答在所有浏览器中都适用。
2013年

8
当心选择器!“ .list li”将选择所有后代LI标记,而不仅仅是直接子代。
Doug Domeny

3
@DougDomeny是正确的。$(".list").children()如果可能的话,最好打电话给它,或者建立具有直接子关系的选择器,例如$(".list > li")
mroncetwice 2014年

1
顺便说一句,这是我用这个答案制作的小提琴的链接。我将代码设置为多功能: jsfiddle.net/mroncetwice/t0whh6fL
mroncetwice 2014年

39

要使此功能适用于包括Chrome在内的所有浏览器,您需要使sort()的回调函数返回-1,0或1。

参见http://inderpreetsingh.com/2010/12/01/chromes-javascript-sort-array-function-is-different-yet-proper/

function sortUL(selector) {
    $(selector).children("li").sort(function(a, b) {
        var upA = $(a).text().toUpperCase();
        var upB = $(b).text().toUpperCase();
        return (upA < upB) ? -1 : (upA > upB) ? 1 : 0;
    }).appendTo(selector);
}
sortUL("ul.mylist");

2
在附加排序后的li元素之前,是否应该从ul.myList中删除所有li元素?
达德(Daud)2012年

2
@Daud,不需要显式删除LI元素。
Doug Domeny

1
使用.localeCompare将对非ASCII字符有所改进。
Doug Domeny 2013年

1
@DougDomeny,为什么不需要显式删除li元素?
bowserm

3
@ bowserm,appendTo方法移动DOM元素,而不是复制它们。
Doug Domeny 2015年

31

如果您使用的是jQuery,则可以执行以下操作:

$(function() {

  var $list = $("#list");

  $list.children().detach().sort(function(a, b) {
    return $(a).text().localeCompare($(b).text());
  }).appendTo($list);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<ul id="list">
  <li>delta</li>
  <li>cat</li>
  <li>alpha</li>
  <li>cat</li>
  <li>beta</li>
  <li>gamma</li>
  <li>gamma</li>
  <li>alpha</li>
  <li>cat</li>
  <li>delta</li>
  <li>bat</li>
  <li>cat</li>
</ul>

请注意,从compare函数返回1和-1(或0和1)是绝对错误的


7

@SolutionYogi的答案就像一个咒语,但似乎使用$ .each比直接附加listitems更为简单和有效:

var mylist = $('#list');
var listitems = mylist.children('li').get();

listitems.sort(function(a, b) {
   return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
})

mylist.empty().append(listitems);

小提琴


$('#list')。empty()-> mylist.empty()会更好。无需再次触摸DOM。
Jacob van Lingen 2014年

绝对,我只是解决了!
Buzut 2014年

这在Internet Explorer(经过版本10测试)中不起作用。
乍得·约翰逊

我刚刚使用IE11进行了测试,实际上,它不起作用。但是,SolutionYogi的代码在IE11下也无法正常工作……对您有用吗?
Buzut 2014年

1

基于Jeetendra Chauhan的答案的改进

$('ul.menu').each(function(){
    $(this).children('li').sort((a,b)=>a.innerText.localeCompare(b.innerText)).appendTo(this);
});

为什么我认为这是一种改进:

  1. 使用each支持多于一个UL运行

  2. 使用children('li')而不是('ul li')很重要,因为我们只想处理直接子级而不是后代

  3. 使用箭头功能(a,b)=>看起来更好(不支持IE)

  4. 用香草innerText代替$(a).text()提速

  5. localeCompare在元素相等的情况下使用香草可以提高速度(在现实生活中很少使用)

  6. 使用appendTo(this)而不是使用另一个选择器将确保即使选择器捕获了多个ul,也不会中断


0

我一直想自己做这个,我对所提供的任何答案都不满意,因为我相信它们是二次时间,并且我需要在清单上的数百个条目中做到这一点。

我最终扩展了jquery,并且我的解决方案使用了 jquery,但可以轻松地对其进行修改以使用纯JavaScript。

我只访问每个项目两次,并执行一次线性排序排序,因此,我认为这应该可以在大型数据集上更快地完成工作,尽管我自由地承认我可能会在这里犯错误:

sortList: function() {
   if (!this.is("ul") || !this.length)
      return
   else {
      var getData = function(ul) {
         var lis     = ul.find('li'),
             liData  = {
               liTexts : []
            }; 

         for(var i = 0; i<lis.length; i++){
             var key              = $(lis[i]).text().trim().toLowerCase().replace(/\s/g, ""),
             attrs                = lis[i].attributes;
             liData[key]          = {},
             liData[key]['attrs'] = {},
             liData[key]['html']  = $(lis[i]).html();

             liData.liTexts.push(key);

             for (var j = 0; j < attrs.length; j++) {
                liData[key]['attrs'][attrs[j].nodeName] = attrs[j].nodeValue;
             }
          }

          return liData;
       },

       processData = function (obj){
          var sortedTexts = obj.liTexts.sort(),
              htmlStr     = '';

          for(var i = 0; i < sortedTexts.length; i++){
             var attrsStr   = '',
                 attributes = obj[sortedTexts[i]].attrs;

             for(attr in attributes){
                var str = attr + "=\'" + attributes[attr] + "\' ";
                attrsStr += str;
             }

             htmlStr += "<li "+ attrsStr + ">" + obj[sortedTexts[i]].html+"</li>";
          }

          return htmlStr;

       };

       this.html(processData(getData(this)));
    }
}


0

的HTML

<ul id="list">
    <li>alpha</li>
    <li>gamma</li>
    <li>beta</li>
</ul>

的JavaScript

function sort(ul) {
    var ul = document.getElementById(ul)
    var liArr = ul.children
    var arr = new Array()
    for (var i = 0; i < liArr.length; i++) {
        arr.push(liArr[i].textContent)
    }
    arr.sort()
    arr.forEach(function(content, index) {
        liArr[index].textContent = content
    })
}

sort("list")

JSFiddle演示https://jsfiddle.net/97oo61nw/

在这里,我们将特定li元素(作为函数参数提供)内的所有元素值推入数组,并使用sort()方法对其进行排序,该方法默认情况下按字母顺序排序。数组排序后,我们使用forEach()方法循环该数组,并用排序后的内容替换所有元素的文本内容ulidarrarrli

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.