简体   繁体   中英

JavaScript: group items by a key, sort items within(!) the groups by another key - how?

in my results Students should be grouped(!) by Room-Id and then, within the group, sorted by age.

Results grouped/sorted by Room:

Name      | R | Age  
-------------------
Student 2 | 1 | 22  
Student 4 | 1 | 25  
Student 3 | 3 | 21  
Student 6 | 3 | 27  
Student 1 | 5 | 29 <- Wrong, should be: Student 5, Room 5, Age 23 
Student 5 | 5 | 23 <- Wrong, should be: Student 1, Room 5, Age 29

My current code (JSFiddle: http://jsfiddle.net/n9KNx/ ):

<script type="text/javascript">
/* add students */
var students = new Array();
students.push({ name: "Student 1", room_id: 5, age: 29 });
students.push({ name: "Student 2", room_id: 1, age: 22 });
students.push({ name: "Student 3", room_id: 3, age: 21 });
students.push({ name: "Student 4", room_id: 1, age: 25 });
students.push({ name: "Student 5", room_id: 5, age: 23 });
students.push({ name: "Student 6", room_id: 3, age: 27 });

/* sort by room_id */
students.sort(function(a, b) {
    return ((a.room_id < b.room_id) ? -1 : ((a.room_id > b.room_id) ? 1 : 0));
});

/* FIXME: sort by age without changing the room order */
/* ... code ... */

/* build HTML output */
var html = '<table>';
html += '<tr><th>Name</th><th>Room</th><th>Age</th></tr>';
for (var i = 0; i < students.length; i++) {
    html += '<tr><td>'+ students[i].name +'</td><td>'+ students[i].room_id +'</td>    <td>'+ students[i].age +'</td></tr>';
}
html += '</table>';

$("#students").html(html);
</script>

<div id="students">...</div>

How would you sort the students by age within each group? I added the code on JSFiddle, feel free to play with it!

The sort function needed to be expanded to cover when the rooms are equal. When the rooms are equal we then compare the age.

students.sort(function(a, b) {
    if(a.room_id < b.room_id){
        return -1;  
    }else if(a.room_id > b.room_id){
        return 1;
    }else{
        if(a.age < b.age){
           return -1
        }else if(a.age > b.age){
          return 1;
        }else{
          return 0;
        }
    }
});

Working Example http://jsfiddle.net/n9KNx/1/

Since you're sorting on numbers, you don't need to do three-way comparisons but just can compute the difference. The solution looks then like this:

students.sort(function(a, b) {
    return (a.room_id - b.room_id) || (a.age - b.age);
});

…and does exactly the same thing as the lengthy snippets from the other answers :-)

students.sort(function(a, b) {
    return ((a.room_id < b.room_id) ? -1 :
              ((a.room_id > b.room_id) ? 1 :
                 ((a.age < b.age) ? -1 :
                    ((a.age > b.age) ? 1 : 0))));
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM