2012-04-06 3 views
1

js + jQueryを使用して関数を書きました。この機能の目的は、テーブルをスキャンし、特定のフィールド(TD)の値のマッチングを持つ行をチェックすることですhttp://jsfiddle.net/anarnold/LpBaW/テーブル行の冗長性をチェックするためのJavaScript + jQuery機能のパフォーマンスが遅い

:ここ

は私の問題を示してjsFiddleへのリンクです。次に、行に一意であるかどうかを示すクラスが割り当てられ、一致する行の数が各行の最終フィールド(td)に出力されます。

それは基本的に、この構造のネストされたループを使用する:各列について

を... マッチのためにテーブル全体をスキャン..

I行を識別する方法は、フィールド(TD)を連結することです各行のテキストを各行の最終フィールド(td)のROWID属性に変換します。

現在のファンクションはうまく動作しますが、大きなテーブル~2000行では非常に遅くなります。

これを達成するには、より効率的で洗練された方法が必要です。どんな助けでも大歓迎です!

+0

'$( "#ビニングTBODY")をチェックアウトする子ども( 'TR')' - 。なぜか '$("#ビニングTBODY > tr ")'? – ThiefMaster

+0

ありがとうございます。間違いなくクリーンですが、目立ったパフォーマンスの改善はありません。 – anarnold

答えて

2

は、結果を格納し、その上に反復する連想配列を使用する例である:ここ

http://jsfiddle.net/AdDMk/

var rowIdCnt = {}; 

function unqOrMsgTest() { 
    // Store counts here 
    var rowIdCnt = {}; 

    // loop through check tds 
    $("#binning tr td[col=check]").each(function() { 

     // grab row identifer to check against other rows   
     var rowId = $(this).attr("rowid"); 

     if (rowId in rowIdCnt) { 
      rowIdCnt[rowId] ++; 
     } else { 
      rowIdCnt[rowId] = 1; 
     } 

    }); 

    // Now iterate over each count and update the table appropriately: 
    $.each(rowIdCnt, function(rowId, cnt) { 
     //this bit of logic picks a class to assign rows   
     var resultClass = "notUnique"; 
     if (cnt < 2) { 
      resultClass = "unique"; 
     } 

     //apply the row class and print the redundancy number into td 
     $('#binning tr td[rowid='+rowId+']').text(cnt).parent().addClass(resultClass); 

    }); 

} 
+0

ありがとうございました。一度それが書かれて参照してくださいそれは明らかです!私は今このアプローチをベンチマークし、結果を投稿します! – anarnold

+0

は、同じテーブルで約45分で実行されます。 – anarnold

0

各テーブルエントリのハッシュ値を作成し、ハッシュテーブルを使用するか、重複をチェックする前にソートするので、ネイバーを比較するだけです。

+0

これははるかに良いアプローチのようです!今すぐそれに取り組む。私の流暢さはまだかなり低いです。誰もがjsでハッシュを使用し、ソートする方法を示すコードのいくつかの行を削除できますか? – anarnold

+0

@Jeff Bは素敵なハッシュテーブルの例を示しました。ソートの方法はあなたのテーブルと実際のフィールドによって異なります – worenga

0

もっと優雅なやり方は、このテーブルを作成する前にデータレベルでこれを行うことです。ここ

+0

ありがとう、vucetica。テーブルは動的です。それはajax呼び出しによって繰り返し追加されます。データへの直接アクセスはないので、テーブルから来る必要があります。 @mightyuhuはデータをハッシュに抽出し、そこで作業することを提案しました。彼のアプローチを今試みている。 – anarnold

+0

ajaxでデータを追加する場合は、さらに簡単です。追加する前に、テーブルに存在しない行だけを追加してください。そのようにすると(あなたの例では)、あなたのテーブルを2000回、JavaScriptの配列を4 000 000回渡します。これはテーブルを4 000 000回通過するよりはるかに高速です。 –

1

は、これを行うのより良好な予備成形する方法です。それらはすべて失敗する - 私は私ができるだけでなく、無効な属性(HTMLタグは特定の属性のみをサポートすることができます。..カスタム属性がdata-接頭辞する必要があります)

$(document).ready(function(){ //this is just to fire the function 
    $("#unqOrMsgTestFire").click(function(){ 
     unqOrMsgTest(); 
    }); 
}); 

function check_unique(row, collection) { 
    var unique = true, rowid = $(row).children('td[data-col=check]')[0].getAttribute('data-rowid'); 
    collection.each(function() { 
     if($(this).children('td[data-col=check]')[0].getAttribute('data-rowid') == rowid) { 
      unique = false; 
     } 
    }); 
    return unique; 
} 

function unqOrMsgTest() { 

    var collection = $("#binning tbody").children('tr'); 

    collection.each(function(i, el){ 
     el.className += check_unique(el, collection.not(el)) ? ' unique' : 'notUnique'; 
    });    

}​ 

http://jsfiddle.net/rlemon/LpBaW/41/ <を修正して冗長DOMを呼び出すなど、多くを削除しましたしかし、それは期待される。

+0

私はちょうど私の2000行のテストをしたし、ひどく失敗します。 – rlemon

+0

私は正直を尊重します。私は間違いなくあなたのフィードバックを再実装します。不正な属性...(これは内部テストツールのためのものですので、標準に準拠していなくても意味的には完璧である必要はありませんが、とにかくそれを実行するのがよい方法です) – anarnold

+0

@rlemon:このコードは読みやすく、それでもネストされたループを実行しているため、パフォーマンスは大きく異なることはなく、恐ろしいことに失敗します。 –

0

は、ここに私の推奨されるソリューションです:

http://jsfiddle.net/j9RXR/29/

function unqOrMsgTest() { 
    var rows = $("#binning tbody").children('tr'); 
    var totalRows = rows.length; 
    var idLookup = {}; 
    var i, rowId, resultClass, checkColumn, rowCount, row; 

    // loops through all rows, convert to jQuery objects and track the IDs 
    for (i = 0; i < totalRows; i++) 
    { 
     row = $(rows[i]); 
     rowId = row.children('td[col="check"]').attr("rowid"); 
     rows[i] = row; 

     idLookup[rowId] = (rowId in idLookup) ? idLookup[rowId] + 1 : 1; 
    } 

    // loop through each row and check them for redundancy 
    for (var i = 0; i < totalRows; i++) 
    { 
     // grab row identifer to check against the id lookup 
     row = rows[i]; 
     checkColumn = row.children('td[col="check"]'); 
     rowId = checkColumn.attr("rowid");  

     //this bit of logic picks a class to assign rows   
     rowCount = idLookup[rowId]; 
     resultClass = rowCount < 2 ? "unique" : "notUnique"; 

     //apply the row class and print the redundancy number into td 
     checkColumn.text(rowCount); 
     row.attr("class", resultClass);   
    };    
}​ 

のidのとカウントを格納する連想配列(またはハッシュ)を使用することをお勧め上記の回答と同様に、私はまた、すべてのコールを削除しましたlist.each(function() {...})に変更し、dom要素からjQueryオブジェクトへの変換回数を最小限に抑えました。

eachの使用を取り除いた理由は、新しい匿名関数が各繰り返しで作成され、スタックスラッシングはもちろんのこと、$(this)からの冗長変換も呼び出されたからです。単純なforループと言うだけで十分ですjQueryの落とし穴の詳細について

jQuery pitfalls to avoid

+0

それは面白いです。しかし、私はあなたのコードを5000項目に対してベンチマークすると1390ミリ秒の実行時間が得られ、コードを '.each()'でベンチマークすると194ミリ秒の実行時間が得られます。あなたの余分なjQueryがオーバーヘッドを追加するかどうか疑問に思いますか? –

+0

興味深い:)あなたはどのブラウザを使用していますか?あなたのソリューションでも194ミリ秒に近づくようには思えません。私はここでサンプルを更新しました:http://jsfiddle.net/j9RXR/35/私たちのソリューションとWin7の両方にChromeを組み込む私はあなたのソリューションを約2倍遅くしています:/チェックする必要がありますこれにもう少し! –

+0

また、私はハードコーディング(私が知っている、私が知っている...)の列によってまともなパフォーマンスの向上を見出しました。 checkColumn = row.children()[5]; ' –

0

http://jsfiddle.net/LpBaW/57/

$(function(){ //this is just to fire the function 
    $("#unqOrMsgTestFire").click(unqOrMsgTest); 
    $("#spawn").click(function(){ 
     var blueprint = $("#binning tbody tr").first(); 
     for(var i = 0; i < 1000; i++) 
      blueprint.clone().appendTo("#binning tbody").find('td[rowid]').attr('rowid', Math.floor(Math.random()*500)); 
    }); 
}); 

function unqOrMsgTest() { 
    console.profile(); 
    var toCheck = $("#binning > tbody > tr > td[col=check]"), 
     ignore = {}, 
     curId, 
     currentlyProcessing, 
     rowsAmount, 
     i; 

    i = toCheck.length - 1; 
    while(i >= 0) { 
     curId = toCheck.eq(i).attr("rowid"); 
     if(!(curId in ignore)) { 
      ignore[curId] = undefined; 

      currentlyProcessing = $("#binning > tbody > tr > td[rowid=" + curId + "]"); 

      rowsAmount = currentlyProcessing.length; 

      currentlyProcessing 
       .text(rowsAmount) 
       .parent().attr('class', rowsAmount > 1 ? "notUnique" : "unique"); 
     } 
     i--; 
    } 
    console.profileEnd(); 
}​ 

     rowsAmount = currentlyProcessing.length; 

     currentlyProcessing 
      .text(rowsAmount) 
      .parent().attr('class', rowsAmount > 1 ? "notUnique" : "unique"); 

     toCheck = toCheck.not(currentlyProcessing); 
    } 
} 
関連する問題