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
이 방법으로 찾은 한 가지 문제는 이동하는 텍스트 일뿐이므로 정렬하기 전에 jQuery.data를 사용하여 DOM 노드에 데이터를 연결하면 정렬 후 잘못된 연결을 가리키고 있다는 것입니다.
Rudism

13
innerHTML로 요소를 이동하는 것은 정렬 후 동일한 요소가 아니기 때문에 나쁜 해결책입니다. 요소에 대한 모든 기존 참조가 손실됩니다. JavaScript에서 바인딩 된 모든 이벤트 리스너가 손실됩니다. innerHTML 대신 요소를 저장하고 정렬 함수 (vals.sort (function (a, b) {return b.innerHTML <a.innerHTML;})) 및 appendChild를 사용하여 요소를 이동하는 것이 좋습니다.
그레인저

3
Buhuuu innerHTML! 사용하지 마십시오. 그것은 Microsoft의 독점적 인 물건이며 W3C에 의해 인정받지 못했습니다.
Steve K

13
IMHO 이것은 끔찍한 대답입니다. DOM 노드를 직렬화하고 다시 직렬화 해제하지 않고 연결된 속성 및 / 또는 이벤트를 파괴하지 않고도 DOM 노드를 재 배열 할 수 있습니다.
Alnitak

3
...하지만 jQuery를 사용한다면 어떻게 할 것입니까?
Matthew

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)로 바꿀 수 있습니까? ?
Amir

26
HL Menken은이 솔루션을 설명하는 인용문을 가지고 있습니다. "모든 문제에 대해 간단하고 우아하며 잘못된 솔루션이 있습니다." 이 프로세스는 O (n ^ 2) 시간에 실행됩니다. 상대적으로 짧은 목록에서는 눈에 띄지 않지만 100 개 이상의 요소가 포함 된 목록에서는 정렬을 마치는 데 3-4 초가 걸립니다.
Nathan Strong

5
@Nathan : "모든 문제에 대해 간단하고 우아하며 잘못된 해결책이 있습니다." -잘못된 해결책은 우아하지 않습니다.
Johann Philipp Strathausen

18
우아하고 흥미로운 것을 볼 수는 있지만 여전히 실패합니다. 우아함이 성공을 의미하지는 않습니다.
Jane Panda

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');. 한 발언 비록 : .text()이어야한다.text().toUpperCase()
쥘 콜레

불행히도이 솔루션은 IE에서 작동하지 않지만 PatrickHecks는 아래 답변을 모든 브라우저에서 작동합니다.
pat

8
선택기를 조심하십시오! ".list li"은 직계 자식뿐만 아니라 모든 하위 LI 태그를 선택합니다.
Doug Domeny

3
@DougDomeny가 맞습니다. 더 나은 호출 할 $(".list").children()가능하면, 또는 같은 직계 자식 관계 선택기 설정$(".list > li")
mroncetwice

1
BTW이 답변을 사용하여 만든 바이올린에 대한 링크입니다. 코드를 올인원 기능으로 설정했습니다. jsfiddle.net/mroncetwice/t0whh6fL
mroncetwice

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에서 제거하지 않아야합니까?
Daud

2
@Daud, LI 요소는 명시 적으로 제거 할 필요가 없습니다.
Doug Domeny

1
.localeCompare를 사용하면 비 ASCII 문자가 향상됩니다.
Doug Domeny

1
@ DougDomeny, li 요소를 명시 적으로 제거하지 않아도되는 이유는 무엇입니까?
bowserm

3
@bowserm, appendTo 메소드는 DOM 요소를 복사하지 않고 이동시킵니다.
Doug Domeny

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

물론 방금 수정했습니다!
Buzut

Internet Explorer (버전 10으로 테스트)에서는 작동하지 않습니다.
채드 존슨

방금 IE11로 테스트했지만 실제로 작동하지 않습니다. 그러나 SolutionYogi의 코드는 IE11에서도 작동하지 않았습니다 ... 그게 효과가 있었습니까?
Buzut

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

나는 이것을 직접하고 싶었고, 나는 그것이 이차 시간이기 때문에 단순히 제공된 대답에 만족하지 못했습니다. 수백 개의 항목 목록 에서이 작업을 수행해야합니다.

나는 jquery를 확장하고 솔루션 jquery를 사용하지만 간단한 자바 스크립트를 사용하도록 쉽게 수정할 수 있습니다.

나는 각 항목에 두 번만 액세스하고 하나의 선형 정렬 정렬을 수행하므로 큰 실수로 인해 더 빠르게 작동해야한다고 생각하지만 실수로 고백 할 수 있다고 생각합니다.

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>

자바 스크립트

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/

여기서는 기본적으로 알파벳순으로 정렬 된 sort () 메서드를 사용하여 배열 하고 정렬하기 위해 특정 (함수 인수로 제공 한) li요소 내부 의 모든 요소 값을 푸시합니다 . 배열 이 정렬 된 후 forEach () 메소드를 사용 하여이 배열을 반복 하고 모든 요소 의 텍스트 내용을 정렬 된 내용으로 바꿉니다.ulidarrarrli

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.