1

我使用 js+jQuery 编写了函数。

这是一个 jsFiddle 的链接,它显示了我的问题:http: //jsfiddle.net/anarnold/LpBaW/

此函数的目标是扫描表并检查具有某些字段 (td) 值匹配的行。然后为行分配一个类,表示它们是否是唯一的,并且匹配的行数被打印到每行的最终字段(td)中。

它基本上使用这种结构的嵌套循环:

对于每一行...扫描整个表以查找匹配项..

我识别行的方法是将每一行的字段 (td) 文本连接到每一行的最后一个字段 (td) 上的 rowid 属性。

当前的功能运行良好,但是对于大约 2000 行的大型表,它会变得非常慢。

必须有一种更高效、更优雅的方式来实现这一点。任何帮助将不胜感激!

4

6 回答 6

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);

    });

}
于 2012-04-06T22:09:12.247 回答
1

这是一种更好的预成型方法。我已经尽可能多地删除了多余的 DOM 调用,并更正了无效属性(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/ <- 他们都失败了,但这是意料之中的。

于 2012-04-06T22:14:02.383 回答
0

为每个表条目创建哈希值并使用哈希表或在检查重复之前对其进行排序,因此您只需要比较邻居。

于 2012-04-06T21:49:37.940 回答
0

更优雅的方法是在构建此表之前在数据级别执行此操作。

于 2012-04-06T21:53:29.557 回答
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 到 $(this) 的冗余转换,更不用说堆栈抖动了。只需说一个简单的 for 循环就足够了,而且速度更快。

有关 jQuery 陷阱的更多信息,请查看要避免的 jQuery 陷阱

于 2012-04-06T22:33:23.827 回答
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 );
    }
}
于 2012-04-06T23:02:39.647 回答