JQuery kullanarak bir listeyi alfabetik olarak nasıl sıralayabilirim?


233

Buradaki derinliğimden biraz uzaktayım ve bunun aslında mümkün olduğunu umuyorum.

Listemdeki tüm öğeleri alfabetik olarak sıralayacak bir işlevi çağırabilmek istiyorum.

Sıralama için jQuery UI bakıyorum ama öyle görünmüyor. Düşüncesi olan var mı?



Underscore.js veya Sugar.js'yi kontrol edin .
Kris Khaira

Yanıtlar:


106

Bunu yapmak için jQuery gerekmez ...

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

Kullanımı kolay...

sortUnorderedList("ID_OF_LIST");

Canlı Demo →


29
Bu yaklaşımla bulduğum bir sorun, yalnızca hareket ettirilen metin olduğundan, sıralamadan önce jQuery.data kullanarak verileri DOM düğümleriyle ilişkilendirirseniz, bu ilişkilendirmelerin artık sıralamadan sonra yanlış düğümlere işaret ediyor olmasıdır.
Rudizm

13
İnnerHTML ile öğeleri taşımak kötü bir çözümdür, çünkü sıralamadan sonra aynı elemanlar değildir. Elemanlara mevcut tüm referanslar kaybolur. JavaScript'ten bağlanan tüm olay dinleyicileri kaybolur. İnnerHTML yerine öğeleri depolamak, bir sıralama işlevi (vals.sort (function (a, b) {return b.innerHTML <a.innerHTML;})) ve öğeleri taşımak için appendChild kullanmak daha iyi olur.
gregers

3
Buhuuu iç HTML! Bunu kullanma. Microsoft'a ait olan şeylerdir ve W3C tarafından asla kabul edilmemiştir.
Steve K

13
IMHO bu korkunç bir cevap. DOM düğümlerini serileştirmeden ve tekrar serileştirmeden ve ekli özellikleri ve / veya olayları yok etmeden yeniden düzenlemek mükemmel bir şekilde mümkündür.
Alnitak

3
... ama jQuery kullanacak olsaydınız, bunu nasıl yapardınız?
Matthew

332

Bunun gibi bir şey:

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

Bu sayfadan: http://www.onemoretake.com/2009/02/25/sorting-elements-with-jquery/

Yukarıdaki kod, sıralanmamış listenizi 'myUL' kimliğiyle sıralar.

VEYA TinySort gibi bir eklenti kullanabilirsiniz. https://github.com/Sjeiti/TinySort


6
Son satır $ (listitems) ile değiştirilebilir. AppendTo (mylist); ?
Amir

26
HL Menken'in bu çözümü açıklayan bir teklifi var: "Her sorun için basit, zarif ve yanlış bir çözüm var." Bu işlem O (n ^ 2) sürede çalışır. Nispeten kısa listelerle fark edilmez, ancak 100'den fazla öğe içeren bir listede sıralamanın tamamlanması 3-4 saniye sürer.
Nathan Strong

5
@Nathan: Hakkında "Her sorun için basit, zarif ve yanlış bir çözüm var." - yanlış bir çözüm zarif değil.
Johann Philipp Strathausen

18
Bir şey izlemek zarif ve ilgi çekici olabilir, ancak yine de başarısız olur. Zarafet başarı anlamına gelmez.
Jane Panda

13
Bu çözüm yanlış değil. Bu soruya cevap veriyor. OP, 100'den fazla öğeden oluşan bir listeyi sıralaması gerektiğini belirtmedi. Onun listesi asla 100 maddeden daha uzun olmayacaksa, bu çözüm mükemmel kabul edilebilir. Çözümün yavaş olduğunu belirtmek için +1, gereksinimleri 'yanlış' olarak karşılayan bir çözüm bildirmek için -1.
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;    
}

canlı demo: http://jsbin.com/eculis/876/edit


15
Bu en iyi cevap. Böyle bile benzerini daha tek satır: $(".list li").sort(function(a, b){return ($(b).text()) < ($(a).text());}).appendTo('.list');. Ancak bir açıklama: .text()olmalı.text().toUpperCase()
Jules Colle

Ne yazık ki bu çözüm IE'de çalışmazken PatrickHecks aşağıdaki cevap tüm tarayıcılarda çalışır.
patg

8
Seçiciye dikkat edin! ".list li" sadece yakın çocukları değil, tüm azalan LI etiketlerini seçecektir.
Doug Domeny

3
@ DougDomeny haklı. $(".list").children()Mümkünse aramak daha iyi , ya da seçiciyi hemen çocuk ilişkisiyle $(".list > li")
kurmak

1
BTW İşte bu cevabı kullanarak yaptığım bir keman link. Kodu bir all-in-one işlevi olarak ayarladım
mroncetwice

39

Bu çalışmanın Chrome dahil tüm tarayıcılarla çalışmasını sağlamak için sort () işlevinin geri arama işlevini -1,0 veya 1 döndürmeniz gerekir.

bkz. 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
Sıralanan li elemanlarını eklemeden önce tüm li elemanları ul.myList'ten kaldırılmamalı mı?
Daud

2
@Daud, LI öğelerinin açıkça kaldırılmasına gerek yoktur.
Doug Domeny

1
.LocaleCompare kullanmak ASCII olmayan karakterler için bir iyileştirme olacaktır.
Doug Domeny

1
@DougDomeny, li öğelerinin neden açıkça kaldırılmasına gerek yok?
bowserm

3
@bowserm, appendTo yöntemi DOM öğelerini kopyalamak yerine hareket ettirir.
Doug Domeny

31

JQuery kullanıyorsanız bunu yapabilirsiniz:

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

Karşılaştırma işlevinden 1 ve -1 (veya 0 ve 1) döndürmenin kesinlikle yanlış olduğunu unutmayın .


7

@ SolutionYogi'nin yanıtı bir cazibe gibi çalışıyor, ancak $ .each kullanmanın doğrudan eklenen liste öğelerinden daha az basit ve verimli olduğu görülüyor:

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

Vaktini boşa harcamak


$ ('# list'). empty () -> mylist.empty () daha iyi olurdu. DOM'ya tekrar dokunmanıza gerek yok.
Jacob van Lingen

Kesinlikle, düzelttim!
Buzut

Bu, Internet Explorer'da (sürüm 10 ile test edilmiştir) çalışmaz.
Chad Johnson

Sadece IE11 ile test ettim ve aslında işe yaramıyor. Ancak SolutionYogi'nin kodu IE11 altında da çalışmadı… Bu sizin için işe yaradı mı?
Buzut

1

Jeetendra Chauhan'ın cevabına dayalı iyileştirme

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

neden bir gelişme olarak görüyorum:

  1. eachbirden fazla ul üzerinde çalışmayı desteklemek için kullanma

  2. children('li')bunun yerine kullanmak ('ul li')önemlidir çünkü torunları değil, yalnızca doğrudan çocukları işlemek istiyoruz

  3. ok işlevini kullanmak (a,b)=>daha iyi görünüyor (IE desteklenmiyor)

  4. hız gelişimi için vanilya innerTextkullanmak$(a).text()

  5. vanilya localeComparekullanımı eşit elemanlar durumunda hızı artırır (gerçek hayatta kullanımda nadirdir)

  6. appendTo(this)başka bir seçici kullanmak yerine kullanmak, seçici birden fazla ul yakalasa bile hiçbir şeyin bozulmamasını sağlayacaktır.


0

Bunu kendim yapmak istiyordum ve verilen cevaplardan herhangi birinden memnun kalmadım çünkü inanıyorum, ikinci dereceden zamanlar ve bunu yüzlerce öğe listelerinde yapmam gerekiyor.

Sonunda jquery uzattım ve benim çözüm kullanır jquery , ancak düz javascript kullanmak için kolayca değiştirilebilir.

Her öğeye yalnızca iki kez erişiyorum ve bir lineeritmik sıralama gerçekleştiriyorum, bu yüzden bu, büyük veri kümelerinde çok daha hızlı olmak için çalışmalı, ancak orada yanlış olabileceğimi itiraf etmeliyim:

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 Demosu https://jsfiddle.net/97oo61nw/

Burada, liöğelerin tüm değerlerini, varsayılan olarak alfabetik olarak sıralanan sort () yöntemini kullanarak sıralamak ve sıralamak için ulbelirli id(işlev bağımsız değişkeni olarak sağladık) ile itiyoruz . Dizi sıralandıktan sonra forEach () yöntemini kullanarak bu diziyi döngüye alırız ve tüm öğelerin metin içeriğini sıralı içerikle değiştiririzarrarrli

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.