22

I have the following DIVs on my page:

<div id="pi_div3">
  Div 3
</div>
<div id="pi_div2">
  Div 2
</div>
<div id="pi_div1">
  Div 1
</div>
<div id="pi_div6">
  Div 6
</div>
<div id="pi_div5">
  Div 5
</div>
<div id="pi_div4">
  Div 4
</div>

I am trying to select the Divs using the jQuery code $("div[id*=pi_div]").

I need the divs to be sorted based on their IDs when I do an each() on the selector. When I loop through the DIVs, the order should be: PI_DIV1, PI_DIV2, PI_DIV3, PI_DIV4, PI_DIV5, PI_DIV6. How can I do that in jQuery?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
PushCode
  • 1,419
  • 3
  • 15
  • 31
  • Sort *after*, not *during*. `jQuery(..)` returns an "array like" object and an there is `Array.sort` that can take a custom compare function. –  Feb 14 '13 at 15:49
  • Here is a solved similar question: [how-may-i-sort-a-list-alphabetically-using-jquery][1] [1]: http://stackoverflow.com/questions/1134976/how-may-i-sort-a-list-alphabetically-using-jquery – Oliver Feb 14 '13 at 15:55

4 Answers4

20

You can call .sort() before calling .each()

$("div[id*=pi_div]").sort(function(a,b){
    if(a.id < b.id) {
        return -1;
    } else {
        return 1;
    }
}).each(function() { console.log($(this).attr("id"));});

EDIT: I was wondering why the other answers are removing the pi_div part of the id and I get it. If you compare based on the "strings" pi_div10 will come before pi_div2.

koopajah
  • 23,792
  • 9
  • 78
  • 104
  • 1
    @HRK : You should accept someone else's answer, mine work just because your number of elements is limited. I let it to explain why it wouldn't work in general – koopajah Feb 14 '13 at 16:07
  • This function is flawed. It compares string values, which will not create the correct result. – Tomalak Feb 14 '13 at 16:08
  • @Tomalak > It is written clearly in the answer and I asked HRK to accept another one. I wanted to leave it to avoid someone making the same mistake. – koopajah Feb 14 '13 at 16:08
  • Your comment was not visible to me before I wrote mine. :) – Tomalak Feb 14 '13 at 16:11
  • @Tomalak > no but the EDIT in the answer was there before my answer was accepted. I can't delete it now that it is accepted, should i flag it ? – koopajah Feb 14 '13 at 16:12
  • 2
    I would wait until the OP comes online again. He's not seen your comment yet. Accepted answers cannot be deleted. – Tomalak Feb 14 '13 at 16:18
8

If you also want to sort them visibly on the page

$('div[id^="pi_div"]').sort(function (a, b) {
    var re = /[^\d]/g;
    return ~~a.id.replace(re, '') > ~~b.id.replace(re, '');
})
.appendTo("#container");

Note the ~~ which converts the values into integers, otherwise they would be compared as strings.

See http://jsfiddle.net/Xjc2T/

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • 1
    I would use `parseInt` or just convert them into numbers using '+'. It's a little more obvious. – Blazemonger Feb 14 '13 at 16:04
  • 3
    @Blazemonger Well, you are right, it would be same thing. However, `~~` also handles `undefined` and `Infinity`, so I tend to use that. – Tomalak Feb 14 '13 at 16:10
  • 2
    Thanks for adding `.appendTo('#container')` that updates elements sort order in the DOM three. – Nik Sumeiko Nov 16 '15 at 18:21
6
$("div[id^=pi_div]").sort(function (a, b) {
    return a.id.replace('pi_div', '') > b.id.replace('pi_div', '');
}).foo();

http://jsfiddle.net/KrX7t/

Ram
  • 143,282
  • 16
  • 168
  • 197
  • 1
    Worth noting that jQuery's `.sort()` method is intended for internal use and is undocumented on purpose. – Blazemonger Feb 14 '13 at 16:03
  • 1
    Strictly speaking, no, it's not an array, or it wouldn't need to have a `toArray()` method. But it looks like a duck and quacks like a duck. – Blazemonger Feb 14 '13 at 16:09
  • 4
    @Blazemonger the .sort method is just inherited from the native Array.prototype.sort method. It's not jQuery's, it is intended for external use, and it's undocumented because it's not part of jquery. – Josh Hibschman Mar 10 '13 at 16:20
3

I would use the Array.sort method. http://jsfiddle.net/LJWrg/

var divArr = $("div[id*=pi_div]");
function cleanId(id) {
    return parseInt(id.replace("pi_div",""),10);
}
Array.prototype.sort.call(divArr,function(a,b) {
    return cleanId(a.id) > cleanId(b.id);
});
divArr.each(function(){
    console.log(this.id);
});

jQuery does come with this method internally defined, so you can shorten it to this (however it uses undocumented methods) http://jsfiddle.net/LJWrg/1/:

var divArr = $("div[id*=pi_div]");
function cleanId(id) {
    return parseInt(id.replace("pi_div",""),10);
}
divArr.sort(function(a,b) {
    return cleanId(a.id) > cleanId(b.id);
});
divArr.each(function(){
    console.log(this.id);
});
Kevin B
  • 94,570
  • 16
  • 163
  • 180