Sorting HTML table by two columns

13,309

To sort by more than one column you write the comparison function like this:

(Comparison function is passed two "rows")

  1. Compare row 1 column 1 with row 2 column 1
    • If they are different then return the result (a +ve or -ve number)
  2. Compare row 1 column 2 with row 2 column 2
    • If they are different then return the result (a +ve or -ve number)
  3. Repeat for remaining columns
  4. Return 0

The following example shows how to write the compare function that sorts by two columns. It is possible to use a loop or recursion to sort by n columns.

$(function() {
  function sortByColumn3(row1, row2) {
    var v1, v2;
    v1 = $(row1).find("td:eq(2)").text();
    v2 = $(row2).find("td:eq(2)").text();
    // for numbers you can simply return a-b instead of checking greater/smaller/equal
    return v1 - v2;
  }

  function sortByColumn3And5(row1, row2) {
    var v1, v2, r;
    v1 = $(row1).find("td:eq(2)").text();
    v2 = $(row2).find("td:eq(2)").text();
    r = v1 - v2;
    if (r === 0) {
      // we have a tie in column 1 values, compare column 2 instead
      v1 = $(row1).find("td:eq(4)").text();
      v2 = $(row2).find("td:eq(4)").text();
      if (v1 < v2) {
        r = -1;
      } else if (v1 > v2) {
        r = 1;
      } else {
        r = 0;
      }
    }
    return r;
  }
  $("#button1, #button2").on("click", function() {
    var rows = $("#table1 tbody tr").detach().get();
    switch (this.id) {
      case "button1":
        rows.sort(sortByColumn3);
        break;
      case "button2":
        rows.sort(sortByColumn3And5);
        break;
    }
    $("#table1 tbody").append(rows);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<input type="button" id="button1" value="sortByColumn3">
<input type="button" id="button2" value="sortByColumn3And5">

<table id="table1" border="1" width="100%">
  <thead>
    <tr>
      <td>1</td>
      <td>2</td>
      <td>3</td>
      <td>4</td>
      <td>5</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>x</td>
      <td>y</td>
      <td>2</td>
      <td>z</td>
      <td>Fish</td>
    </tr>
    <tr>
      <td>y</td>
      <td>z</td>
      <td>1</td>
      <td>x</td>
      <td>Box</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
      <td>7</td>
      <td>y</td>
      <td>Cat</td>
    </tr>
    <tr>
      <td>x</td>
      <td>y</td>
      <td>2</td>
      <td>z</td>
      <td>Dog</td>
    </tr>
    <tr>
      <td>y</td>
      <td>z</td>
      <td>1</td>
      <td>x</td>
      <td>Apple</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
      <td>2</td>
      <td>y</td>
      <td>Box</td>
    </tr>
    <tr>
      <td>x</td>
      <td>y</td>
      <td>2</td>
      <td>z</td>
      <td>Axe</td>
    </tr>
    <tr>
      <td>y</td>
      <td>z</td>
      <td>7</td>
      <td>x</td>
      <td>Box</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
      <td>2</td>
      <td>y</td>
      <td>Answer</td>
    </tr>
    <tr>
      <td>x</td>
      <td>y</td>
      <td>7</td>
      <td>z</td>
      <td>Apple</td>
    </tr>
    <tr>
      <td>y</td>
      <td>z</td>
      <td>6</td>
      <td>x</td>
      <td>Year</td>
    </tr>
    <tr>
      <td>z</td>
      <td>x</td>
      <td>2</td>
      <td>y</td>
      <td>Goat</td>
    </tr>
  </tbody>
</table>

Share:
13,309
Nishant Kumar
Author by

Nishant Kumar

Updated on July 08, 2022

Comments

  • Nishant Kumar
    Nishant Kumar almost 2 years

    I have several columns in a table such as column A,B,C,D and E which I need to show in my HTML page. In some pages I need to show sorted results based on only one column of page, such as for Column "C" which is 3rd column of table. I am able to do this using the below code:

    function Ascending(a, b) {
      if (a < b) return -1;
      if (a > b) return 1;
      return 0;
    }
    var rows = $('#table tr').not(':first').get();
    $('#table tr').slice(1).remove();
    rows.sort(function(rowA, rowB) {
      var keyA = $(rowA).children('td').eq(2).text().toUpperCase();
      var keyB = $(rowB).children('td').eq(2).text().toUpperCase();
      return Ascending(keyA, keyB);
    });
    

    But I have another requirement wherein I need to show the sorted results based on two columns i.e. based on the sorting of Column C in above case, results of column E should also get sorted. For example:

    Before sorting:

    Column C  Column E
    2         Fish
    1         Box
    7         Cat
    2         Dog
    1         Apple
    2         Box
    2         Axe
    7         Box
    2         Answer
    7         Apple
    6         Year
    2         Goat
    

    After sorting Column C only:

    Column C  Column E
    1         Box
    1         Apple
    2         Dog
    2         Fish
    2         Box
    2         Axe
    2         Goat
    2         Answer
    6         Year
    7         Box
    7         Apple
    7         Cat
    

    After sorting Column C then Column E:

    Column C  Column E
    1         Apple
    1         Box
    2         Answer
    2         Axe
    2         Box
    2         Dog
    2         Fish
    2         Goat
    6         Year
    7         Apple
    7         Box
    7         Cat
    

    Example of table wherein M should come below L in second column

    Which I am unable to implement. How can I do it?