jQueryを使用してリストをアルファベット順にソートするにはどうすればよいですか?


233

私はここで自分の深みから少し離れていますが、これが実際に可能であることを願っています。

リスト内のすべてのアイテムをアルファベット順に並べ替える関数を呼び出せるようにしたいのですが。

私はソートのためにjQuery UIを調べてきましたが、それはそうではないようです。何かご意見は?



Underscore.jsまたはSugar.jsを確認してください。
Kris Khaira

回答:


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
このアプローチで見つけた1つの問題は、移動されるのはテキストのみであるため、並べ替えの前にjQuery.dataを使用してDOMノードにデータを関連付けると、並べ替え後にこれらの関連付けが間違ったノードを指すようになるということです。
ルディズム'28年

13
innerHTMLを使用して要素を移動することは、並べ替え後は同じ要素ではないため、不適切な解決策です。要素への既存の参照はすべて失われます。JavaScriptからバインドされたすべてのイベントリスナーは失われます。innerHTMLではなく要素を格納し、並べ替え関数(vals.sort(function(a、b){return b.innerHTML <a.innerHTML;}))を使用して要素を移動することをお勧めします。
グレンジャー2012

3
Buhuuu innerHTML!それを使わないでください。これはMicrosoft独自のものであり、W3Cから認められたことはありません。
スティーブK

13
私見これは恐ろしい答えです。DOMノードをシリアル化したり、逆シリアル化したりすることなく、また添付されているプロパティやイベントを破壊することなく、DOMノードを再配置することは完全に可能です。
アルニタク2013年

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
@ネイサン:「すべての問題に対して、シンプルでエレガント、そして間違った解決策があります。」-まあ、間違ったソリューションはエレガントではありません。
ヨハンフィリップストラトハウゼン2011年

18
エレガントで興味をそそるものはありますが、それでも失敗します。エレガンスは成功を意味するものではありません。
ジェーンパンダ

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');。ただし、1つの発言:する.text()必要があります.text().toUpperCase()
Jules Colle

残念ながら、このソリューションはIEでは機能しませんが、以下のPatrickHecksの回答はすべてのブラウザーで機能します。
2013年

8
セレクターに注意!「.list li」は、直接の子だけでなく、すべての子孫LIタグを選択します。
Doug Domeny 2013年

3
@DougDomenyは正しいです。$(".list").children()可能な場合はを呼び出すか、セレクターを次のような直接の子関係に設定することをお$(".list > li")
勧めします

1
ところでここに私がこの答えを使って作ったフィドルへのリンクがあります。コードをオールインワン関数として設定しました: jsfiddle.net/mroncetwice/t0whh6fL
mroncetwice '17

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要素を追加する前に、すべてのli要素をul.myListから削除する必要はありませんか?
ダウド2012

2
@ Daud、LI要素を明示的に削除する必要はありません。
Doug Domeny 2013年

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>

比較関数から1と-1(または0と1)を返すのはまったく間違っていることに注意してください。


7

@SolutionYogiの答えは魅力のように機能しますが、$ .eachを使用することは、リストアイテムを直接追加するよりも簡単で効率的ではないようです:

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でテスト済み)では機能しません。
Chad Johnson

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

私はこれを自分で行うことを考えていましたが、答えが2次の時間であり、何百もの項目のリストでこれを行う必要があるという理由だけで、提供された答えのどれにも満足できませんでした。

私は結局jqueryを拡張することになり、私のソリューション jqueryを使用しましたが、ストレートjavascriptを使用するように簡単に変更できました。

私は各アイテムに2回しかアクセスせず、1つの線形ソートを実行するので、大規模なデータセットの方がはるかに高速になるはずです。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.