【问题标题】:Sort table both numerically and alphabetically using Javascript使用 Javascript 按数字和字母顺序对表格进行排序
【发布时间】:2018-03-29 17:09:58
【问题描述】:

我有一个表格,它通过单击标题来工作,然后每次单击标题时都会按升序和降序对列进行排序。它按字母顺序对所有内容进行排序,但我需要它也能够按数字排序。

在同一列中的数字超过个位数之前,它似乎有效。

这是 HTML 代码:(忽略 NFL 内容,只是测试此表的数据)

<div id="supAll">
            <table border="1" class="supTable">
                <tr> 
                    <th onclick="sortTable('supTable', 0)">Team</th>
                    <th onclick="sortTable('supTable', 1)">SB Wins</th>
                    <th onclick="sortTable('supTable', 2)">SB Losses</th>
                    <th onclick="sortTable('supTable', 3)">Last Won</th>
                </tr>
                <tr class="nfc nfcWest">
                    <td>Arizona Cardinals</td>
                    <td>0</td>
                    <td>1</td>
                    <td>-</td>
                </tr>
                <tr class="nfc nfcSouth">
                    <td>Atlanta Falcons</td>
                    <td>10</td>
                    <td>2</td>
                    <td>-</td>
                </tr>
                <tr class="afc afcNorth">
                    <td>Baltimore Ravens</td>
                    <td>2</td>
                    <td>0</td>
                    <td>2012</td>
                </tr>
                <tr class="afc afcEast">
                    <td>Buffalo Bills</td>
                    <td>11</td>
                    <td>4</td>
                    <td>-</td>
                </tr>
                <tr class="nfc nfcSouth">
                    <td>Carolina Panthers</td>
                    <td>22</td>
                    <td>2</td>
                    <td>-</td>
                </tr>
                <tr class="nfc nfcNorth">
                    <td>Chicago Bears</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1985</td>
                </tr>
                <tr class="afc afcNorth">
                    <td>Cincinnati Bengals</td>
                    <td>0</td>
                    <td>2</td>
                    <td>-</td>
                </tr>
                <tr class="afc afcNorth">
                    <td>Cleveland Browns</td>
                    <td>0</td>
                    <td>0</td>
                    <td>-</td>
                </tr>
                <tr class="nfc nfcEast">
                    <td>Dallas Cowboys</td>
                    <td>5</td>
                    <td>3</td>
                    <td>1995</td>
                </tr>
                <tr class="afc afcWest">
                    <td>Denver Broncos</td>
                    <td>3</td>
                    <td>5</td>
                    <td>2015</td>
                </tr>
                <tr class="nfc nfcNorth">
                    <td>Detroit Lions</td>
                    <td>0</td>
                    <td>0</td>
                    <td>-</td>
                </tr>
                <tr class="nfc nfcNorth">
                    <td>Green Bay Packers*</td>
                    <td>4</td>
                    <td>1</td>
                    <td>2010</td>
                </tr>
                <tr class="afc afcSouth">
                    <td>Houston Texans</td>
                    <td>0</td>
                    <td>0</td>
                    <td>-</td>
                </tr>
                <tr class="afc afcSouth">
                    <td>Indianapolis Colts</td>
                    <td>2</td>
                    <td>2</td>
                    <td>2006</td>
                </tr>
                <tr class="afc afcSouth">
                    <td>Jacksonville Jaguars</td>
                    <td>0</td>
                    <td>0</td>
                    <td>-</td>
                </tr>
                <tr class="afc afcWest">
                    <td>Kansas Chiefs*</td>
                    <td>1</td>
                    <td>1</td>
                    <td>1969</td>
                </tr>
                <tr class="afc afcWest">
                    <td>Los Angeles Chargers</td>
                    <td>0</td>
                    <td>1</td>
                    <td>-</td>
                </tr>
                <tr class="nfc nfcWest">
                    <td>Los Angeles Rams</td>
                    <td>1</td>
                    <td>2</td>
                    <td>1999</td>
                </tr>
                <tr class="afc afcEast">
                    <td>Miami Dolphins</td>
                    <td>2</td>
                    <td>3</td>
                    <td>1973</td>
                </tr>
                <tr class="nfc nfcNorth">
                    <td>Minnesota Vikings</td>
                    <td>0</td>
                    <td>4</td>
                    <td>-</td>
                </tr>
                <tr class="afc afcEast">
                    <td>New England Patriots</td>
                    <td>5</td>
                    <td>4</td>
                    <td>2016</td>
                </tr>
                <tr class="nfc nfcSouth">
                    <td>New Orleans Saints</td>
                    <td>1</td>
                    <td>1</td>
                    <td>2009</td>
                </tr>
                <tr class="nfc nfcEast">
                    <td>New York Giants</td>
                    <td>4</td>
                    <td>1</td>
                    <td>2011</td>
                </tr>
                <tr class="afc afcEast">
                    <td>New York Jets*</td>
                    <td>1</td>
                    <td>0</td>
                    <td>1968</td>
                </tr>
                <tr class="afc afcWest">
                    <td>Oakland Raiders</td>
                    <td>3</td>
                    <td>2</td>
                    <td>1983</td>
                </tr>
                <tr class="nfc nfcEast">
                    <td>Philadelphia Eagles</td>
                    <td>0</td>
                    <td>2</td>
                    <td>-</td>
                </tr>
                <tr class="afc afcNorth">
                    <td>Pittsburgh Steelers</td>
                    <td>6</td>
                    <td>2</td>
                    <td>2008</td>
                </tr>
                <tr class="nfc nfcWest">
                    <td>San Francisco 49ers</td>
                    <td>5</td>
                    <td>5</td>
                    <td>1994</td>
                </tr>
                <tr class="nfc nfcWest">
                    <td>Seattle Seahawks</td>
                    <td>1</td>
                    <td>2</td>
                    <td>2013</td>
                </tr>
                <tr class="nfc nfcSouth">
                    <td>Tampa Bay Buccaneers</td>
                    <td>1</td>
                    <td>0</td>
                    <td>2002</td>
                </tr>
                <tr class="afc afcSouth">
                    <td>Tennessee Titans</td>
                    <td>0</td>
                    <td>1</td>
                    <td>-</td>
                </tr>
                <tr class="nfc nfcEast">
                    <td>Washington Redskins</td>
                    <td>3</td>
                    <td>2</td>
                    <td>1991</td>
                </tr>
            </table>
        </div>      
    </div>

下面是 Javascript 代码:

function sortTable(tableClass, n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;

table = document.getElementsByClassName(tableClass)[0];
switching = true;
dir = "asc";
while (switching) {
    switching = false;
    rows = table.getElementsByTagName("TR");
    for (i = 1; i < (rows.length - 1); i++) {
        shouldSwitch = false;
        x = rows[i].getElementsByTagName("TD")[n];
        y = rows[i + 1].getElementsByTagName("TD")[n];
        if (dir == "asc") {
            if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
                shouldSwitch= true;
                break;
            }
        } else if (dir == "desc") {
            if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
                shouldSwitch= true;
                break;
            }
        }
    }
    if (shouldSwitch) {
        rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
        switching = true;
        switchcount ++;      
    } else {
        if (switchcount == 0 && dir == "asc") {
            dir = "desc";
            switching = true;
        }
    }
}

}

如果您运行您可以在中间列中看到的代码,其中有不同大小的数字,它不再正确地对它们进行排序。

有什么方法可以使用此代码/功能,以便我的表格可以按字母和数字排序(当它超过单个数字时)?如果没有,有人可以帮我解决这个问题。

编辑 - 这已经解决了!如果您查看 Hendeca 和 Teldri 的以下代码,您将看到已解决的代码。他们的两个版本都可以工作。

【问题讨论】:

    标签: javascript jquery html sorting html-table


    【解决方案1】:

    如果是数字,则需要将表格单元格值转换为数字,如果是名称,则将其保留为字符串。这样做将使比较适用于两种情况。这是一些更新的代码:

    function sortTable(tableClass, n) {
      var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
    
      table = document.getElementsByClassName(tableClass)[0];
      switching = true;
      dir = "asc";
      while (switching) {
          switching = false;
          rows = table.getElementsByTagName("TR");
          for (i = 1; i < (rows.length - 1); i++) {
              shouldSwitch = false;
              x = rows[i].getElementsByTagName("TD")[n];
              y = rows[i + 1].getElementsByTagName("TD")[n];
              var xContent = (isNaN(x.innerHTML)) 
                  ? (x.innerHTML.toLowerCase() === '-')
                        ? 0 : x.innerHTML.toLowerCase()
                  : parseFloat(x.innerHTML);
              var yContent = (isNaN(y.innerHTML)) 
                  ? (y.innerHTML.toLowerCase() === '-')
                        ? 0 : y.innerHTML.toLowerCase()
                  : parseFloat(y.innerHTML);
              if (dir == "asc") {
                  if (xContent > yContent) {
                      shouldSwitch= true;
                      break;
                  }
              } else if (dir == "desc") {
                  if (xContent < yContent) {
                      shouldSwitch= true;
                      break;
                  }
              }
          }
          if (shouldSwitch) {
              rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
              switching = true;
              switchcount ++;      
          } else {
              if (switchcount == 0 && dir == "asc") {
                  dir = "desc";
                  switching = true;
              }
          }
       }
    }
    

    通过测试字符串是否为数字,您可以确定是否转换该值。这是相关的更改:

    var xContent = (isNaN(x.innerHTML)) ? x.innerHTML.toLowerCase() : parseFloat(x.innerHTML);
    var yContent = (isNaN(y.innerHTML)) ? y.innerHTML.toLowerCase() : parseFloat(y.innerHTML);
    

    编辑:添加了一些代码来处理 - 字符的情况,并将数字字符串转换为浮点数而不是整数来处理十进制数。新的检查是:

    var xContent = (isNaN(x.innerHTML)) 
            ? (x.innerHTML.toLowerCase() === '-')
                ? 0 : x.innerHTML.toLowerCase()
            : parseFloat(x.innerHTML);
    var yContent = (isNaN(y.innerHTML)) 
            ? (y.innerHTML.toLowerCase() === '-')
                ? 0 : y.innerHTML.toLowerCase()
            : parseFloat(y.innerHTML);
    

    【讨论】:

    • 此代码无效,我认为是因为您放置了更改。我认为它应该在 'if (dir == "asc") {' 的上方和外部如果您查看此页面上的其他答案,则该代码有效并且与您的相似。如果您阅读了我的最新回复,我有一个新问题……在某些列中,我使用“-”作为空白来表示等效于“N/A”,这显然不是一个数字。对于包含该符号的任何列,它都无法正确排序。有没有办法解决?或者一种转换该符号的方法,使其本质上等于 0(不必写 0)?
    • @bevstar7 你是对的,它是在错误的地方!我还添加了一个测试来处理列中- 的情况。如果遇到- 用于排序,这只会返回0。此代码适用于我并处理 - 案例。
    • 我设法使用其他代码来解决我的问题(他们也解决了“-”问题),但只是尝试了你的,它也有效!感谢您的帮助。
    • 你好。刚刚注意到此代码的另一个问题。在某些列上,我使用“。”在数字之前作为百分比指标,例如'.600'。在这些列上,它不会对任何内容进行排序。你知道解决这个问题的方法吗?
    • 我已将数字更改为前面没有小数点,但如果需要,可以放在中间。例如。 '.535' 变为 '53.5'。但是,某些数字的排序高于/低于应有的排序。例如。 '48.3' 高于 '48.6' 即使它是一个较小的数字。有没有办法解决这个问题?
    【解决方案2】:

    您应该在比较之前将数值解析为整数或浮点数

    所以

    if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
    

    改成

    if (parseInt(x.innerHTML) > parseInt(y.innerHTML)) {
    

    如果没有数字则比较字符串

    var cmpX=isNaN(parseInt(x.innerHTML))?x.innerHTML.toLowerCase():parseInt(x.innerHTML);
    
    var cmpY=isNaN(parseInt(y.innerHTML))?y.innerHTML.toLowerCase():parseInt(y.innerHTML);
    
    if (parseInt(cmpX) > parseInt(cmpY)) {
    

    把你的函数改成这样:

    function sortTable(tableClass, n) {
    var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
    
    table = document.getElementsByClassName(tableClass)[0];
    switching = true;
    dir = "asc";
    while (switching) {
        switching = false;
        rows = table.getElementsByTagName("TR");
        for (i = 1; i < (rows.length - 1); i++) {
            shouldSwitch = false;
            x = rows[i].getElementsByTagName("TD")[n];
            y = rows[i + 1].getElementsByTagName("TD")[n];
                    var cmpX=isNaN(parseInt(x.innerHTML))?x.innerHTML.toLowerCase():parseInt(x.innerHTML);
                    var cmpY=isNaN(parseInt(y.innerHTML))?y.innerHTML.toLowerCase():parseInt(y.innerHTML);
    cmpX=(cmpX=='-')?0:cmpX;
    cmpY=(cmpY=='-')?0:cmpY;
            if (dir == "asc") {
                if (cmpX > cmpY) {
                    shouldSwitch= true;
                    break;
                }
            } else if (dir == "desc") {
                if (cmpX < cmpY) {
                    shouldSwitch= true;
                    break;
                }
            }
        }
        if (shouldSwitch) {
            rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
            switching = true;
            switchcount ++;      
        } else {
            if (switchcount == 0 && dir == "asc") {
                dir = "desc";
                switching = true;
            }
        }
    }
    }
    

    【讨论】:

    • 嗨,这非常适合整理我的数字列,但它阻止了我按字母顺序对第一列进行排序。现在只能对数字进行排序。
    • 现在很好用,谢谢!我现在只有一个新问题.....在某些列中,我使用“-”作为空白来表示相当于“N/A”,这显然不是一个数字。对于包含该符号的任何列,它都无法正确排序。有没有办法解决?或者一种转换该符号的方法,使其本质上等于 0(不必写 0)?
    • 你好。刚刚注意到此代码的另一个问题。在某些列上,我使用“。”在数字之前作为百分比指标,例如'.600'。在这些列上,它不会对任何内容进行排序。你知道解决这个问题的方法吗?
    • 我已将数字更改为前面没有小数点,但如果需要,可以放在中间。例如。 '.535' 变为 '53.5'。但是,某些数字的排序高于/低于应有的排序。例如。 '48.3' 高于 '48.6' 即使它是一个较小的数字。有没有办法解决这个问题?
    • 只使用 parseFloat() 而不是 parseInt()
    【解决方案3】:

    问题实际上是您的数字是字符串。因此,“14”小于“4”。可以先尝试转换为数字,如果是NaN,则可以将其作为字符串进行测试,否则,作为数字进行测试。

    _sortTable: function(n, context) {
        var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
        table = document.getElementById(context.options.id);
        switching = true;
    
        //Set the sorting direction to ascending:
        dir = "asc"; 
        /*Make a loop that will continue until
        no switching has been done:*/
        while (switching) {
            //start by saying: no switching is done:
            switching = false;
            rows = table.getElementsByClassName("row");
            /*Loop through all table rows (except the
            first, which contains table headers):*/
            for (i = 0; i < (rows.length - 1); i++) {
                //start by saying there should be no switching:
                shouldSwitch = false;
                /*Get the two elements you want to compare,
                one from current row and one from the next:*/
                x = rows[i].getElementsByClassName("cell")[n];
                y = rows[i + 1].getElementsByClassName("cell")[n];
                /*check if the two rows should switch place,
                based on the direction, asc or desc:*/
                x = Number(x.innerHTML.toLowerCase()) ? Number(x.innerHTML.toLowerCase()) : x.innerHTML.toLowerCase();
                y = Number(y.innerHTML.toLowerCase()) ? Number(y.innerHTML.toLowerCase()) : y.innerHTML.toLowerCase();
    
                if (dir == "asc") {
                    if (x > y) {
                        //if so, mark as a switch and break the loop:
                        shouldSwitch= true;
                        break;
                    }
                } else if (dir == "desc") {
                    if (x < y) {
                        //if so, mark as a switch and break the loop:
                        shouldSwitch= true;
                        break;
                    }
                }
            }
            if (shouldSwitch) {
                /*If a switch has been marked, make the switch
                and mark that a switch has been done:*/
                rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
                switching = true;
                //Each time a switch is done, increase this count by 1:
                switchcount ++; 
            } else {
                /*If no switching has been done AND the direction is "asc",
                set the direction to "desc" and run the while loop again.*/
                if (switchcount == 0 && dir == "asc") {
                dir = "desc";
                switching = true;
                }
            }
        }
    

    【讨论】:

    • 我该怎么做?
    • 此页面上的其他两个答案设法解决了我的问题。不过感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 2018-11-19
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 2019-05-14
    相关资源
    最近更新 更多