0

編集: ピートは、フィールドに数字が含まれている場合に機能する非常に優れたソリューションを提供しましたが、文字列もソートできるようにする必要があります-何かアイデアはありますか?

クリックされた列に基づいてテーブルをソートするJavaScriptソートアルゴリズムを作成しようとしています.

一部の列はテキストで、一部の列は数値です。

列をクリックすると、sort(X,Y) が呼び出されます。X は列番号であるため、並べ替えのためにどのセルを比較するかがわかります。Y はモード、つまり昇順または降順です。

sort 関数のコードは次のとおりです。

function sort(field, mode) {
var tabrows = 0;
$(".data tr").each(function() { if($(this).hasClass("hdr")) { } else {tabrows++;} });   
var swapped;
do {
        swapped = false;
        for (var i=0;i< tabrows; i++) {

            var j = i + 3;
            var k = i + 4;  

            var row1 = $(".data tr:nth-child("+j+")");
            var row2 = $(".data tr:nth-child("+k+")");

            var field1 = row1.find("td:eq("+field+")").text();      
            var field2 = row2.find("td:eq("+field+")").text();

            if(shouldswap(field1, field2, mode)) {
                swaprows(row1, row2);
                swapped = true;
            }
        }
    } while (swapped);
}

shouldswap 関数は次のとおりです。

function shouldswap(field1, field2,mode) {


    if(field1 > field2) {
            if(mode==1) {   
                return true;
            } else {
                return false;
            }   
    }

    return false;

}

swaprows 関数のコード:

function swaprows(row1, row2) {
      row2.insertBefore(row1);
}

これによりブラウザがフリーズ/ロックアップする理由を誰でも理解できますか。私はかなり長い間これに取り組んできたので、新鮮な目でばかげたことを指摘できると思います! どんな助けでも大歓迎です:)

4

2 に答える 2

1

問題は、jQuery コンストラクターを何度も呼び出して重い操作を行っていることです (.find()複雑なセレクターを使用するなど)。したがって、あなたの機能はただ遅いだけであり、それがおそらく問題です。

幸いなことに、JavaScript には QuickSort (非常に高速な並べ替え機能) のネイティブ実装があり、おそらくニーズに対応してくれるでしょう。コストのかかる呼び出しの削減と組み合わせると、コードは非常に効率的になります。コードを次のように変更します。

var sortByField = function(field, mode) {
    var numExp = /^-?\d*\.?\d+$/;
    var $rows = $(".data tr:not(.hdr)"), $table = $(".data");
    $rows.each(function () {
        this.fieldVal = $(this).find("td:eq("+field+")").text();
        if(numExp.test(this.fieldVal)) { //if field is numeric, convert it to a number
            this.fieldVal = +this.fieldVal;
        }
    }).sort(function (a, b) {
        if (mode === 1) {
            return (a.fieldVal > b.fieldVal) ? -1 : 1;    
        }    
        return (a.fieldVal < b.fieldVal) ? -1 : 1;
    }).detach().each(function () {
        $(this).appendTo($table);
    });
};

これは、1 ページに複数のテーブルがある場合にはうまく機能しません (すべてが同じテーブルにあると想定されるため)。したがって、それを行う場合は、テーブルまたはテーブル セレクターをパラメーターとして渡す必要があります。しかし、それは簡単に修正できます。ここで私のソリューションの動作を確認できます。

http://jsfiddle.net/r8wtK/ (更新)

コードよりもはるかに効率的であり、「フリーズ」をかなり (完全に) 減らす必要があります。

アップデート:

OPは、一部のフィールドに文字列が含まれている可能性があることに注意しました。数字で文字列比較を行うのは良くありません。辞書順 (例: ) が返されるから"10" < "2"です。そこで、並べ替えを行う前に、データが数値であるかどうかを確認するテストを追加しました。

于 2012-09-12T16:51:14.913 に答える
0

i行インデックスを取得するために3 と 4 を追加している可能性がありますか? したがって、iが に到達すると、および(tabrows-1)のインデックスを持つ行にアクセスしようとしているように見えます。あなたのロジックを正しく理解していれば、これらは範囲外であるため、、 、およびは空になります。したがって、あなたが. これは理にかなっていますか、それとも私はあなたの論理を誤解していますか?(tabrows+2)(tabrows+3)row1row2field1field2mode==1

その場合は、 for ループを次のように変更するだけでよいと思います。

for (var i=0;i< tabrows-4; i++) {
     // your code
}

j に 3 を、k に 4 を加える目的は何ですか? 比較したくない上部に 3 行のデータがありますか?

于 2012-09-12T16:44:24.797 に答える