Làm cách nào để sắp xếp danh sách theo thứ tự abc bằng jQuery?


233

Tôi hơi sâu sắc ở đây và tôi hy vọng điều này thực sự có thể.

Tôi muốn có thể gọi một chức năng sắp xếp tất cả các mục trong danh sách của tôi theo thứ tự bảng chữ cái.

Tôi đã xem qua giao diện người dùng jQuery để sắp xếp nhưng dường như không phải vậy. Có suy nghĩ gì không?



Hãy xem Underscore.js hoặc Sugar.js .
Kris Khaira

Câu trả lời:


106

Bạn không cần jQuery để làm điều này ...

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

Dễ sử dụng ...

sortUnorderedList("ID_OF_LIST");

Demo trực tiếp →


28
Một vấn đề mà tôi tìm thấy với cách tiếp cận này là, vì đó chỉ là văn bản được di chuyển xung quanh, nếu bạn liên kết dữ liệu với các nút DOM bằng jQuery.data trước khi sắp xếp, các liên kết đó hiện đang trỏ đến các nút sai sau khi sắp xếp.
Rudism

12
Di chuyển các phần tử với InternalHTML là một giải pháp tồi vì chúng không phải là các phần tử giống nhau sau khi sắp xếp. Tất cả các tham chiếu hiện có đến các yếu tố bị mất. Tất cả các trình lắng nghe sự kiện bị ràng buộc từ JavaScript đều bị mất. Sẽ tốt hơn nếu lưu trữ các phần tử thay vì InternalHTML, sử dụng hàm sort (vals.sort (function (a, b) {return b.innerHTML <a.innerHTML;})) và appendChild để di chuyển các phần tử.
Gregers

3
Buhuuu bên trongHTML! Đừng sử dụng nó. Đó là công cụ độc quyền của Microsoft và không bao giờ được W3C thừa nhận.
Steve K

13
IMHO đây là một câu trả lời khủng khiếp. Hoàn toàn có thể sắp xếp lại các nút DOM mà không cần tuần tự hóa chúng và giải nén chúng một lần nữa và không phá hủy bất kỳ thuộc tính và / hoặc sự kiện đính kèm nào.
Alnitak

3
... Nhưng nếu bạn sử dụng jQuery, bạn sẽ làm thế nào?
Matthew

332

Một cái gì đó như thế này:

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

Từ trang này: http://www.onemoretake.com/2009/02/25/sorting-elements-with-jquery/

Mã ở trên sẽ sắp xếp danh sách không theo thứ tự của bạn với id 'myUL'.

HOẶC bạn có thể sử dụng một plugin như TinySort. https://github.com/Sjeiti/TinySort


6
Dòng cuối cùng có thể được thay thế bằng $ (listitems) .appendTo (mylist); ?
Amir

26
HL Menken có một trích dẫn mô tả giải pháp này: "Đối với mọi vấn đề, có một giải pháp đơn giản, thanh lịch và sai lầm". Quá trình này chạy trong thời gian O (n ^ 2). Nó không đáng chú ý với các danh sách tương đối ngắn, nhưng trên một danh sách chứa hơn 100 yếu tố, phải mất 3-4 giây để hoàn thành việc sắp xếp.
Nathan Strong

5
@Nathan: Giới thiệu "Đối với mọi vấn đề, có một giải pháp đơn giản, thanh lịch và sai." - tốt, một giải pháp sai là không thanh lịch.
Johann Philipp Strathausen

18
Một cái gì đó có thể thanh lịch và hấp dẫn để xem, nhưng vẫn thất bại. Elegance không ngụ ý thành công.
Jane Panda

13
Giải pháp này không sai. Nó trả lời câu hỏi. OP đã không xác định rằng anh ta cần sắp xếp một danh sách hơn 100 mặt hàng. Nếu danh sách của anh ta sẽ không bao giờ dài hơn 100 mặt hàng thì giải pháp này là hoàn toàn chấp nhận được. +1 để chỉ ra rằng giải pháp chậm, -1 khi khai báo một giải pháp đáp ứng các yêu cầu là 'sai'.
Linh hồn Samurai

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

bản demo trực tiếp: http://jsbin.com/eculis/876/edit


15
Đây là câu trả lời tốt nhất. Tôi thậm chí thích nó trong một dòng duy nhất như thế này : $(".list li").sort(function(a, b){return ($(b).text()) < ($(a).text());}).appendTo('.list');. Một nhận xét mặc dù: .text()nên là.text().toUpperCase()
Jules Colle

Thật không may, giải pháp này không hoạt động trong IE trong khi PatrickHecks trả lời dưới đây hoạt động trong tất cả các trình duyệt.
patg

8
Cẩn thận với bộ chọn! ".list li" sẽ chọn tất cả các thẻ LI hậu duệ, không chỉ các con ngay lập tức.
Doug Domeny

3
@DougDomeny nói đúng. Tốt hơn là gọi $(".list").children(), nếu có thể, hoặc thiết lập bộ chọn với mối quan hệ con ngay lập tức như$(".list > li")
mroncetwice 17/12/14

1
BTW Đây là một liên kết đến một câu đố tôi đã thực hiện bằng cách sử dụng câu trả lời này. Tôi thiết lập mã dưới dạng hàm tất cả trong một: jsfiddle.net/mroncetwice/t0whh6fL
mroncetwice 17/12/14

39

Để làm cho công việc này hoạt động với tất cả các trình duyệt bao gồm Chrome, bạn cần làm cho hàm gọi lại của sort () trả về -1,0 hoặc 1.

xem http://inderpreetsingh.com/2010/12/01/chromes-javascript-sort-array-feft-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
Không nên xóa tất cả các phần tử li khỏi ul.myList trước khi nối các phần tử li được sắp xếp?
Daud

2
@Daud, các phần tử LI không cần phải được loại bỏ rõ ràng.
Doug Domeny

1
Sử dụng .localeCompare sẽ là một cải tiến cho các ký tự không phải ASCII.
Doug Domeny

1
@DougDomeny, tại sao các yếu tố li không cần phải được loại bỏ rõ ràng?
bowserm

3
@bowserm, phương thức appendTo di chuyển các phần tử DOM thay vì sao chép chúng.
Doug Domeny

31

Nếu bạn đang sử dụng jQuery, bạn có thể làm điều này:

$(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>

Lưu ý rằng trả về 1 và -1 (hoặc 0 và 1) từ hàm so sánh là hoàn toàn sai .


7

Câu trả lời @ SolutionYogi hoạt động như một cơ duyên, nhưng có vẻ như việc sử dụng $ .each ít đơn giản và hiệu quả hơn so với các danh sách bổ sung trực tiếp:

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

Vĩ cầm


$ ('# list'). blank () -> mylist.empty () sẽ tốt hơn. Không cần phải chạm vào DOM một lần nữa.
Jacob van Lingen

Tuyệt đối, tôi chỉ sửa nó!
Buzut

Điều này không hoạt động trong Internet Explorer (được thử nghiệm với phiên bản 10).
Chad Johnson

Tôi mới thử nghiệm với IE11 và thực tế, nó không hoạt động. Nhưng mã của SolutionYogi không hoạt động trong IE11, điều đó có hiệu quả với bạn không?
Buzut

1

cải thiện dựa trên câu trả lời của Jeetendra Chauhan

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

tại sao tôi coi đó là một cải tiến:

  1. sử dụng eachđể hỗ trợ chạy trên nhiều hơn một ul

  2. sử dụng children('li')thay vì ('ul li')rất quan trọng vì chúng tôi chỉ muốn xử lý trẻ em trực tiếp chứ không phải con cháu

  3. sử dụng chức năng mũi tên (a,b)=>trông có vẻ tốt hơn (IE không được hỗ trợ)

  4. sử dụng vanilla innerTextthay vì $(a).text()cải thiện tốc độ

  5. sử dụng vanilla localeComparecải thiện tốc độ trong trường hợp các yếu tố bằng nhau (hiếm khi sử dụng trong cuộc sống thực)

  6. sử dụng appendTo(this)thay vì sử dụng bộ chọn khác sẽ đảm bảo rằng ngay cả khi bộ chọn bắt được nhiều hơn một ul vẫn không có gì bị hỏng


0

Tôi đang tìm cách tự làm điều này và tôi không hài lòng với bất kỳ câu trả lời nào được cung cấp đơn giản bởi vì, tôi tin rằng, chúng là thời gian bậc hai, và tôi cần phải làm điều này trong danh sách hàng trăm mục dài.

Tôi đã kết thúc việc mở rộng jquery và giải pháp của tôi sử dụng jquery, nhưng có thể dễ dàng được sửa đổi để sử dụng javascript thẳng.

Tôi chỉ truy cập mỗi mục hai lần và thực hiện một loại tuyến tính, do đó, tôi nghĩ rằng, việc này sẽ nhanh hơn rất nhiều trên các tập dữ liệu lớn, mặc dù tôi tự do thú nhận rằng tôi có thể bị nhầm lẫn ở đó:

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")

Bản trình diễn JSFiddle https://jsfiddle.net/97oo61nw/

Ở đây chúng ta sẽ đẩy tất cả các giá trị của licác phần tử bên trong ulvới cụ thể id(mà chúng ta đã cung cấp làm đối số hàm) sang mảng arrvà sắp xếp nó bằng phương thức sort () được sắp xếp theo thứ tự bảng chữ cái theo mặc định. Sau khi mảng arrđược sắp xếp, chúng tôi lặp lại mảng này bằng phương thức forEach () và chỉ thay thế nội dung văn bản của tất cả các lithành phần bằng nội dung được sắp xếp

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.