Bagaimana saya bisa mengurutkan daftar berdasarkan abjad menggunakan jQuery?

233

Saya sedikit keluar dari kedalaman saya di sini dan saya berharap ini benar-benar mungkin.

Saya ingin dapat memanggil fungsi yang akan mengurutkan semua item dalam daftar saya berdasarkan abjad.

Saya sudah mencari-cari di jQuery UI untuk menyortir tetapi sepertinya tidak. Adakah pikiran?

Shog9
sumber
Lihat Underscore.js atau Sugar.js .
Kris Khaira

Jawaban:

106

Anda tidak perlu jQuery untuk melakukan ini ...

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

Mudah digunakan...

sortUnorderedList("ID_OF_LIST");

Demo Langsung →

Josh Stodola
sumber
30
Satu masalah yang saya temukan dengan pendekatan ini adalah bahwa, karena hanya teks yang dipindahkan, jika Anda mengaitkan data ke node DOM menggunakan jQuery.data sebelum menyortir, asosiasi tersebut sekarang menunjuk ke node yang salah setelah mengurutkan.
Rudism
13
Memindahkan elemen dengan innerHTML adalah solusi yang buruk karena mereka bukan elemen yang sama setelah pengurutan. Semua referensi yang ada ke elemen hilang. Semua pendengar acara terikat dari JavaScript hilang. Akan lebih baik untuk menyimpan elemen daripada innerHTML, gunakan fungsi sortir (vals.sort (function (a, b) {return b.innerHTML <a.innerHTML;})) dan tambahkanChild untuk memindahkan elemen.
gregers
4
Buhuuu innerHTML! Jangan gunakan itu. Ini adalah hak milik Microsoft dan tidak pernah diakui oleh W3C.
Steve K
14
IMHO ini adalah jawaban yang mengerikan. Sangat mungkin untuk mengatur ulang node DOM tanpa membuat serial mereka dan deserialising lagi, dan tanpa merusak properti dan / atau peristiwa yang terlampir.
Alnitak
4
... tetapi jika Anda menggunakan jQuery, bagaimana Anda melakukannya?
Matius
332

Sesuatu seperti ini:

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

Dari halaman ini: http://www.onemoretake.com/2009/02/25/sorting-elements-with-jquery/

Kode di atas akan mengurutkan daftar tidak berurutan Anda dengan id 'myUL'.

ATAU Anda dapat menggunakan plugin seperti TinySort. https://github.com/Sjeiti/TinySort

SolutionYogi
sumber
6
Bisakah baris terakhir diganti dengan $ (listitems). AppendTo (mylist); ?
Amir
26
HL Menken memiliki kutipan yang menggambarkan solusi ini: "Untuk setiap masalah, ada solusi yang sederhana, elegan, dan salah." Proses ini berjalan dalam waktu O (n ^ 2). Ini tidak terlihat dengan daftar yang relatif singkat, tetapi pada daftar yang berisi lebih dari 100 elemen dibutuhkan 3-4 detik untuk menyelesaikan penyortiran.
Nathan Strong
5
@Nathan: Tentang "Untuk setiap masalah, ada solusi yang sederhana, elegan, dan salah." - yah, solusi yang salah tidak elegan.
Johann Philipp Strathausen
18
Sesuatu dapat menjadi elegan dan menarik untuk ditonton, tetapi masih gagal. Keanggunan tidak menyiratkan kesuksesan.
Jane Panda
13
Solusi ini tidak salah. Itu menjawab pertanyaan. OP tidak menentukan bahwa ia perlu mengurutkan daftar lebih dari 100 item. Jika daftarnya tidak akan lebih dari 100 item, solusi ini dapat diterima. +1 untuk menunjukkan bahwa solusinya lambat, -1 untuk menyatakan solusi yang memenuhi persyaratan sebagai 'salah'.
Samurai Soul
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;    
}

live demo: http://jsbin.com/eculis/876/edit

Jeetendra Chauhan
sumber
15
Ini jawaban terbaik. Aku bahkan seperti itu dalam satu baris seperti ini: $(".list li").sort(function(a, b){return ($(b).text()) < ($(a).text());}).appendTo('.list');. Satu komentar meskipun: .text()harus.text().toUpperCase()
Jules Colle
Sayangnya solusi ini tidak berfungsi di IE sementara PatrickHecks menjawab di bawah ini berfungsi di semua browser.
patg
8
Waspadalah terhadap pemilih! ".list li" akan memilih semua tag LI turunan, bukan hanya anak langsung.
Doug Domeny
3
@DougDomeny benar. Lebih baik menelepon $(".list").children(), jika mungkin, atau mengatur pemilih dengan hubungan anak langsung seperti$(".list > li")
mroncetwice
1
BTW Ini tautan ke biola yang saya buat menggunakan jawaban ini. Saya mengatur kode sebagai fungsi all-in-one: jsfiddle.net/mroncetwice/t0whh6fL
mroncetwice
39

Untuk membuat ini berfungsi dengan semua browser termasuk Chrome Anda harus membuat fungsi callback sort () mengembalikan -1,0 atau 1.

lihat 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");
PatrickHeck
sumber
2
Bukankah semua elemen li harus dihapus dari ul.myList sebelum menambahkan elemen li yang diurutkan?
Daud
2
@Daud, elemen LI tidak perlu dihapus secara eksplisit.
Doug Domeny
1
Menggunakan .localeCompare akan menjadi peningkatan untuk karakter non-ASCII.
Doug Domeny
1
@DougDomeny, mengapa elemen li tidak perlu dihapus secara eksplisit?
bowserm
3
@bowserm, metode appToTo memindahkan elemen DOM daripada menyalinnya.
Doug Domeny
31

Jika Anda menggunakan jQuery, Anda dapat melakukan ini:

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

Perhatikan bahwa mengembalikan 1 dan -1 (atau 0 dan 1) dari fungsi bandingkan benar-benar salah .

Salman A
sumber
7

@ SolutionYogi's jawaban berfungsi seperti pesona, tetapi tampaknya menggunakan $ .each kurang mudah dan efisien daripada langsung menambahkan daftar item:

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

Biola

Buzut
sumber
$ ('# list'). empty () -> mylist.empty () akan lebih baik. Tidak perlu menyentuh DOM lagi.
Jacob van Lingen
Tentu saja, saya baru saja memperbaikinya!
Buzut
Ini tidak berfungsi di Internet Explorer (diuji dengan versi 10).
Chad Johnson
Saya baru saja menguji dengan IE11 dan pada kenyataannya, itu tidak berhasil. Tetapi kode SolutionYogi tidak berfungsi di bawah IE11 ... Apakah itu berhasil untuk Anda?
Buzut
1

perbaikan berdasarkan jawaban Jeetendra Chauhan

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

mengapa saya menganggapnya sebagai peningkatan:

  1. gunakan eachuntuk mendukung berjalan di lebih dari satu ul

  2. menggunakan children('li')bukan ('ul li')penting karena kami hanya ingin memproses anak-anak langsung dan bukan keturunan

  3. menggunakan fungsi panah (a,b)=>hanya terlihat lebih baik (IE tidak didukung)

  4. menggunakan vanilla innerTextbukan $(a).text()untuk peningkatan kecepatan

  5. menggunakan vanila localeComparemeningkatkan kecepatan jika elemen yang sama (jarang digunakan dalam kehidupan nyata)

  6. menggunakan appendTo(this)daripada menggunakan pemilih lain akan memastikan bahwa bahkan jika pemilih menangkap lebih dari satu ul tetap tidak ada yang rusak

oriadam
sumber
0

Saya ingin melakukan ini sendiri, dan saya tidak puas dengan jawaban yang diberikan hanya karena, saya percaya, itu adalah waktu kuadratik, dan saya perlu melakukan ini pada daftar ratusan item.

Saya akhirnya memperluas jquery, dan solusi saya menggunakan jquery, tetapi dapat dengan mudah dimodifikasi untuk menggunakan javascript lurus.

Saya hanya mengakses setiap item dua kali, dan melakukan satu jenis linearitmik, jadi ini seharusnya, saya pikir, bekerja jauh lebih cepat pada kumpulan data besar, meskipun saya dengan bebas mengaku bahwa saya bisa saja salah di sana:

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)));
    }
}
Keanehan
sumber
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")

Demo JSFiddle https://jsfiddle.net/97oo61nw/

Di sini kita mendorong semua nilai lielemen di dalam uldengan spesifik id(yang kami sediakan sebagai argumen fungsi) untuk mengatur arrdan mengurutkannya menggunakan metode sort () yang diurutkan secara alfabetis secara default. Setelah array arrdiurutkan kita loop array ini menggunakan metode forEach () dan hanya mengganti konten teks semua lielemen dengan konten yang diurutkan

Mikhail
sumber