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

248

我有点力不从心,希望这是可以实现的。

我想调用一个函数,它可以按字母顺序对我的列表中所有项目进行排序。

我一直在查找jQuery UI进行排序,但似乎不是这个。 有什么想法吗?


7
什么是使用jQuery对无序列表(ul)或有序列表(ol)进行排序的最简单方法? - gen_Eric
请查看 Underscore.jsSugar.js - Kris Khaira
10个回答

351

6
最后一行可以替换为$(listitems).appendTo(mylist);吗? - Amir
26
H. L. Menken曾说过一句话来形容这个解决方案:“对于每个问题,都有一个简单、优雅而错误的解决方案。” 这个过程的时间复杂度为O(n^2)。在相对较短的列表中可能不会注意到,但对于包含100多个元素的列表,它需要3-4秒才能完成排序。 - Nathan Strong
5
关于“每个问题都有一个简单、优雅但错误的解决方案”的说法,错误的解决方案并不优雅。 - Johann Philipp Strathausen
19
某些事物可能看起来优雅、有趣,但仍然失败。优雅并不意味着成功。 - Jane Panda
15
这个解决方案并不是错误的,它回答了这个问题。原帖并没有具体说明需要对超过100个项目的列表进行排序。如果他的列表永远不会超过100个项目,那么这个解决方案是完全可以接受的。点赞表示指出这个解决方案较慢,扣分表示将符合要求的解决方案称为“错误”。 - Samurai Soul
显示剩余7条评论

104

不需要使用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");

现场演示 →


32
我发现这种方法的一个问题是,由于只是移动了文本,如果在排序之前使用jQuery.data将数据与DOM节点相关联,那么在排序后,这些关联就会指向错误的节点。 - Rudism
14
使用 innerHTML 移动元素是不好的解决方案,因为排序后它们不再是同一元素。所有对这些元素的引用都将丢失。从 JavaScript 绑定的所有事件侦听器也将丢失。最好存储元素而不是 innerHTML,使用排序函数(vals.sort(function(a, b) {return b.innerHTML < a.innerHTML;})),并使用 appendChild 来移动元素。 - gregers
4
不要使用innerHTML!它是微软专有的东西,从未被W3C认可。 - Stephan Kristyn
14
在我看来这是一个糟糕的答案。完全有可能重新排列DOM节点而不需要将它们序列化和反序列化,并且不会破坏任何已附加的属性和/或事件。 - Alnitak
4
如果你要使用jQuery,你会怎么做? - Matthew
显示剩余8条评论

102
$(".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


16
这是最好的答案。我甚至喜欢这样一行代码:$(".list li").sort(function(a, b){return ($(b).text()) < ($(a).text());}).appendTo('.list');。不过要注意一点:.text() 应该改为 .text().toUpperCase(). - Jules Colle
8
小心选择器!“.list li”会选中所有后代LI标签,而不仅仅是直接子元素。 - Doug Domeny
3
@DougDomeny是正确的。如果可能的话,最好调用$(".list").children(),或者设置具有直接子关系的选择器,例如$(".list > li") - mroncetwice
1
顺便提一下,这是一个使用该答案的fiddle链接。我将代码设置为单个函数:http://jsfiddle.net/mroncetwice/t0whh6fL/ - mroncetwice
这个答案是错误的。当文本相同时它不会返回0。 - Salman A
显示剩余2条评论

42

2
在将排序后的li元素附加到ul.myList之前,难道不应该从中删除所有li元素吗? - Daud
2
@Daud,LI元素不需要显式删除。 - Doug Domeny
1
使用.localeCompare对于非ASCII字符将是一种改进。 - Doug Domeny
1
@DougDomeny,为什么li元素不需要显式删除? - bowserm
3
"appendTo" 方法会将 DOM 元素移动而非复制它们。 - Doug Domeny

37

如果你正在使用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>

请注意,从比较函数中返回1和-1(或0和1)是完全错误的


这绝对是太棒了,惊人的,不可思议的!! - Danielle Lpz

8
@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);

Fiddle


$('#list').empty() --> mylist.empty() 会更好,无需再次操作DOM。 - Jacob van Lingen
绝对的,我刚刚修好了! - Buzut
这在Internet Explorer中不起作用(已测试版本为10)。 - Chad Johnson
我刚刚在IE11上进行了测试,事实上它不起作用。但是SolutionYogi的代码在IE11下也没有起作用...那对你有用吗? - Buzut

6

基于 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,也不会出现问题


资源友好型解决方案,强烈推荐。 - Moxet Jan

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元素的所有值推入具有特定id(我们作为函数参数提供)的ul中的数组arr中,并使用默认情况下按字母顺序排序的sort()方法对其进行排序。排序完成后,我们使用forEach()方法循环遍历该数组,并仅替换所有li元素的文本内容为已排序的内容。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接