可以使这种更优雅/递归

时间:2010-10-05 08:14:35

标签: javascript jquery algorithm sorting

我有一张桌子,需要按几列排序 - 让我们说按音乐排序的音乐,然后按艺术家,专辑等排序。或者您可以按艺术家/专辑/曲目排序。这就是我在jquery中提出的:

function tableSort (by) {                                                                             
    var mylist = $('#mainList');                                                                      
    var listitems = $('.row').get();                                                                                                                                               
    listitems.sort(function(a, b) {                                                                   
        var cidA=$(a).attr('id');                                                       
        var cidB=$(b).attr('id');                                                       
        var i=[1,2,4,3];                                                                              
        var compA=[];                                                                                 
        var compB=[];                                                                                 
        compA[0]=$(a).find('.album').html();                                     
        compB[0]=$(b).find('.album').html();;                                    
        compA[1]=$(a).find('.artist').html();             
        compB[1]=$(b).find('.artist').html();             
        compA[2]=$(a).find('.genre').html();                                                             
        compB[2]=$(b).find('.genre').html();                                                             
        compA[3]=$(a).find('.track').val();                                                          
        compB[3]=$(b).find('.track').val();                                                          
        switch (by) {                                                                                 
            case 'genre->artist->album':
                i=[2,0,1,3];                                                                          
                break;                                                                                
            case 'genre->album->artist':                                                                             
                i=[2,1,0,3];                                                                          
                break;                                                                                
            default:                                                                                  
                compA='';                                                                             
                compB='';                                                                             
        }                                                                                             
        var comp=(compA[i[0]] < compB[i[0]]) ? -1 : (compA[i[0]] > compB[i[0]]) ? 1 : 0;              
        if (comp==0) comp=(compA[i[1]] < compB[i[1]]) ? -1 : (compA[i[1]] > compB[i[1]]) ? 1 : 0;     
        if (comp==0) comp=(compA[i[2]] < compB[i[2]]) ? -1 : (compA[i[2]] > compB[i[2]]) ? 1 : 0;     
        if (comp==0) comp=(compA[i[3]] < compB[i[3]]) ? -1 : (compA[i[3]] > compB[i[3]]) ? 1 : 0;     
        return comp;                                                                                  
    });                                                                                               

$.each(listitems, function(i, v) {                                                                    
    var id=$(v).attr('id').split('_')[1];                                                             
    mylist.append(v);                                                                                 
    });                                                                                               
}

这对我有3-4个订单,但必须有更优雅和可扩展的方式!

6 个答案:

答案 0 :(得分:2)

未经测试但应该有效:

listitems.sort(function(a, b) { 
    var $a=$(a),$b=$(b),
        i=[1,2,4,3],  
        compA=[],   
        compB=[],
        cols=['album', 'artist', 'genre', 'track'];
    for(var c=0; c<cols.length; c++)
    {
        var fn=cols[c]==="track" ? "val" : "html";
        compA.push($a.find("."+cols[c])[fn]());
        compB.push($b.find("."+cols[c])[fn]());
    }
    switch (by) { 
        case 'genre->artist->album':
            i=[2,0,1,3];
            break;
        case 'genre->album->artist':
            i=[2,1,0,3];
            break;
        /*default: 
            compA='';   //WHY???
            compB='';*/
    }
    for(c=0; c<i.length; c++)
    {
        if(compA[i[c]]<compB[i[c]]) return -1;
        else if(compA[i[c]]>compB[i[c]]) return 1;
    }
    return 0;
});

答案 1 :(得分:1)

如果您不介意使用插件,请尝试tablesorter或轻量级tinytable

答案 2 :(得分:1)

我建议使用这样的插件。

快速谷歌搜索显示tablesorter,我相信你会找到你想要的一切。缩小版本也只有12kb,所以加载到网站不是一个大问题。

答案 3 :(得分:1)

mck89有一个很好的答案,但我修复了数字排序&amp;尝试将其全部清理干净(demo):

HTML

<table>
 <tr><td colspan=2>Sort:</td></tr>
 <tr><td>Direction:</td><td><select class="dir"><option value="asc">Ascending</option><option value="desc">Descending</option></select></td></tr>
 <tr><td>Order:</td><td><ul class="order"><li>Album <span>-&gt;</span></li><li>Artist <span>-&gt;</span></li><li>Genre <span>-&gt;</span></li><li>Track <span style="display:none">-&gt;</span></li></ul></td></tr>
 <tr><td colspan=2><button>Sort</button></td></tr>
</table>
<br>
<table id="mainList">
 <thead>
  <tr><th>Album</th><th>Artist</th><th>Genre</th><th>Track</th></tr>
 </thead>
 <tbody>
  <tr><td>...</td><td>...</td><td>...</td><td>#</td></tr>
  ...
 </tbody>
</table>

脚本

$(document).ready(function(){
 $('.order').sortable({
  update: function(e,ui){
   $('.order span').show().filter(':last').hide(); // hide last arrow
  }
 });

 $(':button').click(function(){
  var table = ['Album', 'Artist', 'Genre', 'Track'],
   order = [];
  $('.order li').each(function(){
   order.push( $.inArray( $(this).text().replace(' ->',''), table ) );
  });
  tableSort(order, $('.dir').val());
 })
})

 function tableSort(by,dir){
  var mylist = $('#mainList'),
   listitems = mylist.find('tbody tr').get();

  listitems.sort(function(a, b) {
   var $a = $(a),
    $b = $(b),
    i = by,
    compA = [],
    compB = [],
    c;

   for(c=0; c<3; c++){
    compA.push($a.find('td').eq(c).html()); // Alphabetical
    compB.push($b.find('td').eq(c).html());
   }
    compA.push(('0' + $a.find('td:last').html()).slice(-2)); // Numerical (2 digit numbers)
    compB.push(('0' + $b.find('td:last').html()).slice(-2)); // use '00' + ....slice(-3) for 3 digit numbers, etc...

   for(c=0; c<i.length; c++){
    return (dir == 'asc') ?
     ((compA[i[c]] < compB[i[c]]) ? -1 : (compA[i[c]] > compB[i[c]]) ? 1 : 0) : // ascending sort
     ((compA[i[c]] > compB[i[c]]) ? -1 : (compA[i[c]] < compB[i[c]]) ? 1 : 0)   // descending sort
   }
  });

  $.each(listitems, function(i, v) {
   mylist.append(v);
  });
 }

答案 4 :(得分:0)

我接下来推荐一个插件来处理排序并将潜在的错误发现卸载到社区。我想到了jqGrid,但我不认为你选择的选择太少会产生问题:)

答案 5 :(得分:0)

我的javascript / jQuery不是很好,但是这里可能有用的一般技术是从所选列构建一个复合排序键,然后对其进行排序。

为此,您需要确定每列的最大可能长度,将每个排序列中的值填充到其最大值,然后将排序列中的值连接起来以生成单个复合排序键。

例如,如果排序顺序是流派/专辑/艺术家,并且这些字段的最大长度为20/100/100,那么对于每一行,复合排序键为

pad(genre, 20) + pad(album, 100) + pad(artist, 100)

其中pad是一个将给定文本填充到给定长度的函数,带有空格。

对于给定的排序列集,您可以定义一个以行作为输入并返回复合排序键的函数。然后只对这些(单个)值进行排序。填充和连接确保每行的排序键具有相同的长度,并且自然字符串排序将提供您想要的顺序。