DataTables 对字符串而不是数字进行排序

Posted

技术标签:

【中文标题】DataTables 对字符串而不是数字进行排序【英文标题】:DataTables sorts strings instead of numeric 【发布时间】:2012-07-05 16:24:01 【问题描述】:

我正在使用jquery.datatables 在数据表列中显示数字。数字被格式化为在千单位之间有空格(如123 456 789)。不幸的是,这种数字格式会引发 string 排序而不是 number 排序(请参阅本问题末尾的屏幕截图)。

我已经确定:

function _fnSort(oSettings, bApplyClasses) 是排序的核心函数。 在这个函数中,使用了动态函数排序方法(如果if (!window.runtime) 为真则执行)

使用的字符串排序函数是以下两个函数。

/*
* text sorting
*/
"string-asc": function(a, b) 
    var x = a.toLowerCase();
    var y = b.toLowerCase();
    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
,

"string-desc": function(a, b) 
    var x = a.toLowerCase();
    var y = b.toLowerCase();
    return ((x < y) ? 1 : ((x > y) ? -1 : 0));
,

我的javascript知识很差,这里最好的方法是什么?

    调整字符串排序函数以检测 格式化数以千计 的情况,并进行比较(我猜这在大型数据集上会很慢)。 提供专用于千位格式的数字排序功能?在这种情况下 您将如何编码? 如何向核心排序功能指示使用这个特殊的数字排序功能?

这是排序现在的样子:

【问题讨论】:

【参考方案1】:

要对这种值进行排序,可以使用这个排序函数:

var sortFunction=function(a, b)​
    var ia = parseInt(a.split(' ').join(''), 10);
    var ib = parseInt(b.split(' ').join(''), 10);
    return ia-ib;
;

测试:

var data = ['3 333', '100 333', '22 000', '1 333'];
console.log(data.sort(sortFunction));

使用合理数量的值,这将足够快。如果您没有检测到性能问题,则不应尝试丰富数据。

编辑:

其实the documentation提出了一个合适的(类似的)排序函数:

jQuery.extend( jQuery.fn.dataTableExt.oSort, 
    "formatted_numbers-pre": function ( a ) 
        a = (a==="-") ? 0 : a.replace( /[^\d\-\.]/g, "" );
        return parseFloat( a );
    ,

    "formatted_numbers-asc": function ( a, b ) 
        return a - b;
    ,

    "formatted_numbers-desc": function ( a, b ) 
        return b - a;
    
 );

添加此扩展后,您只需设置列的sType

【讨论】:

太棒了!但是我怎么能强制 _fnSort() 对相关列使用这个排序函数呢? 这里是 DataTables 的作者 - 很好的答案 - 投了赞成票。我建议标记为正确/接受:-)。唯一的错字是 sType 作为大写的“T”:datatables.net/ref#sType。还值得指出的是,还有很多其他的排序插件(有些具有类型检测功能)-datatables.net/plug-ins/sorting 嗨。抱歉打错了,现已修正。 太棒了!今天下午我会试试这个,然后告诉你:) 好吧,我偶然发现了另一个问题:如何“设置我的列的 sType”。我可以在文档“如何使用 DataTables 插件排序函数(基于类型)”部分中看到 javascript 代码。如果我在我的 html 中定义了大量的 dataTable,我该如何使用这个 javascript 代码?理想情况下,我会想象像 XX【参考方案2】:

好的,经过大量搜索,我找到了替代解决方案。 dystroyAllan Jardine 提出的解决方案当然更干净。但这意味着触摸 HTML 和在my case 中,触摸 HTML 会引发像下面这样一个棘手的消息框。

所以我的解决方案是触摸 javascript 字符串排序算法,在数字和文本大小写之间切换。我希望它可以通过使用isDigit(sa.charAt[0]) 之类的东西更清洁,但尽管我做了所有尝试,它还是不起作用。至少这个解决方案是有效的,并不意味着任何明显的性能成本:

    /*
    * text + integer sorting
    */
    "string-asc": function(a, b) 
       var sa = a.toString();
       if(sa.length > 0) 
          // Don't know why, isDigit(sa.charAt[0]) doesn't work??
          var ca = sa.substring(0,1);
          if(ca === "0" || ca === "1" || ca === "2" || ca === "3" || ca === "4" || ca === "5" || ca === "6" || ca === "7" || ca === "8" || ca === "9") 
             var x1 = parseInt(a.split(' ').join(''), 10);
             var y1 = parseInt(b.split(' ').join(''), 10);
             return x1 - y1;
          
       
       var x = a.toLowerCase();
       var y = b.toLowerCase();
       return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    ,

    "string-desc": function(a, b) 
        var sa = a.toString();
        if(sa.length > 0) 
           var ca = sa.substring(0,1);
           if(ca === "0" || ca === "1" || ca === "2" || ca === "3" || ca === "4" || ca === "5" || ca === "6" || ca === "7" || ca === "8" || ca === "9") 
              var x1 = parseInt(a.split(' ').join(''), 10);
              var y1 = parseInt(b.split(' ').join(''), 10);
              return y1 - x1;
           
        
        var x = a.toLowerCase();
        var y = b.toLowerCase();
        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
    ,

【讨论】:

【参考方案3】:

对于正在阅读本文并希望获得数字之间空格的完整答案的任何人:

  jQuery.extend( jQuery.fn.dataTableExt.oSort, 
      "formatted_numbers-pre": function ( a ) 
        a = (a===" ") ? 0 : a.replace( /[^\d\-\.]/g, "" );
        return parseFloat( a );
      ,

      "formatted_numbers-asc": function ( a, b ) 
        return a - b;
      ,

      "formatted_numbers-desc": function ( a, b ) 
        return b - a;
      
   );

    $('.myTable').DataTable(
      "columnDefs": [
         "type": "formatted_numbers", "targets": 4 
      ],
    );
  

【讨论】:

【参考方案4】:

在构建 DataTable 时只需设置小数点,如下所示:

var main_table = $('#main_list').DataTable(
    ajax: 
        url: "/api/your/data",
        dataSrc: ''
    ,
    columns: [
         data: "Col1" ,
         data: "Col2" ,
         data: "Col3" ,
         data: "Col4" 
    ],
    language: 
        /* -----> */ "decimal": ",", // <---------
        "emptyTable": "Keine Daten in der Tabelle verfügbar",
        "info": "Anzeigen von _START_ bis _END_ von _TOTAL_ Einträgen",
        "infoEmpty": "Anzeigen von 0 bis 0 von 0 Einträgen",
        "infoFiltered": "(filtriert von_MAX_ Gesamteinträge)",
        "infoPostFix": "",
        /* -----> */ "thousands": ".", // <---------
        "lengthMenu": "_MENU_ Einträge anzeigen",
        "loadingRecords": "Laden...",
        "processing": "Verarbeitung...",
        "search": "Suche:",
        "zeroRecords": "Keine passenden Datensätze gefunden",
        "paginate": 
            "first": "Erste",
            "last": "Letzte",
            "next": "Nächste",
            "previous": "Vorherige"
        ,
        "aria": 
            "sortAscending": ": aufsteigend sortieren",
            "sortDescending": ": absteigend sortieren"
        
    ,
    columnDefs: [
        //set german formatting

            render: function (data, type, row) 
                return formatDE(data,2);
            ,
            targets: [2, 4, 5]
        ,
        

            render: function (data, type, row) 
                return formatDE(data,0);
            ,
            targets: [3]
        
    ],
    pageLength: 50);

如果你更深入地研究jquery.dataTables.js,你会发现他们有一个函数可以确定每列值的类型并捕获格式

【讨论】:

以上是关于DataTables 对字符串而不是数字进行排序的主要内容,如果未能解决你的问题,请参考以下文章

自定义按值的日期部分对 DataTables 列进行排序

DataTables 根据 TD 属性值对 html 表进行排序

对 QTableWidget 中的数字列进行排序

数据表 - 用点对格式化数字进行排序

在 jQuery DataTables 中使用锚标记对列进行排序

如何在javascript中对字符串进行数字排序