JavaScript+;用于检查表行冗余的jQuery函数

JavaScript+;用于检查表行冗余的jQuery函数,javascript,jquery,html-table,matching,redundancy,Javascript,Jquery,Html Table,Matching,Redundancy,我使用js+jQuery编写了这个函数 下面是一个指向JSFIDLE的链接,它显示了我的问题: 此函数的目标是扫描一个表并检查具有某些字段(td)值匹配的行。然后为行分配一个类,表示它们是否唯一,匹配行的数量将打印到每行的最终字段(td)中 它基本上使用这种结构的嵌套循环: 对于每一行。。。 扫描整个表以查找匹配项 我识别行的方法是将每行的字段(td)文本连接到每行的最终字段(td)上的rowid属性中 当前的函数工作正常,但对于大表~2000行,它的速度非常慢 必须有一种更有效、更优雅的方法来

我使用js+jQuery编写了这个函数

下面是一个指向JSFIDLE的链接,它显示了我的问题:

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

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

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

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

当前的函数工作正常,但对于大表~2000行,它的速度非常慢


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

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

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

下面是一个使用关联数组存储结果,然后对其进行迭代的示例:

var rowIdCnt={};
函数unqOrMsgTest(){
//商店在这里计数
var rowIdCnt={};
//循环检查tds
$(“#binning tr td[col=check]”)。每个(函数(){
//抓取行标识符以对照其他行进行检查
var rowId=$(this.attr(“rowId”);
if(rowIdCnt中的rowId){
rowIdCnt[rowId]++;
}否则{
rowIdCnt[rowId]=1;
}
});
//现在迭代每个计数并适当更新表:
$.each(rowIdCnt,函数)(rowId,cnt){
//这种逻辑选择一个类来分配行
var resultClass=“notUnique”;
if(cnt<2){
resultClass=“唯一”;
}
//应用row类并将冗余号打印到td中
$('#binning tr td[rowid='+rowid+']').text(cnt.parent().addClass(resultClass);
});
}

这里有一种更好的预成型方法。我已删除了尽可能多的冗余DOM调用,并更正了无效属性(HTML标记只能支持某些属性..自定义属性需要以
数据-
作为前缀)


以下是我推荐的解决方案:

函数unqOrMsgTest(){
变量行=$(“#binning tbody”).children('tr');
var totalRows=rows.length;
var idLookup={};
变量i、rowId、resultClass、checkColumn、rowCount、row;
//循环所有行,转换为jQuery对象并跟踪ID
对于(i=0;i
与上面建议使用关联数组(或哈希)存储id和计数的答案类似,我还删除了对
list.each(function(){…})
的所有调用,并最小化了从dom元素到jQuery对象的转换次数

我之所以不使用
each
,是因为每次迭代都会创建一个新的匿名函数,还调用了从this到$(this)的冗余转换,更不用说堆栈抖动了。只需说一个简单的for循环就足够了,而且速度更快

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

$(function(){//这只是为了启动函数
$(“#unqOrMsgTestFire”)。单击(unqOrMsgTest);
$(“#繁殖”)。单击(函数(){
var blueprint=$(“#binning tbody tr”).first();
对于(变量i=0;i<1000;i++)
blueprint.clone().appendTo(“#binning tbody”).find('td[rowid')).attr('rowid',Math.floor(Math.random()*500));
});
});
函数unqOrMsgTest(){
console.profile();
var-toCheck=$(“#binning>tbody>tr>td[col=check]”,
忽略={},
居里,
当前正在处理,
罗萨蒙特,
我
i=toCheck.length-1;
而(i>=0){
curId=toCheck.eq(i).attr(“rowid”);
如果(!(居里忽略)){
忽略[curId]=未定义;
currentlyProcessing=$(“#binning>tbody>tr>td[rowid=“+curId+”);
rowsAmount=currentlyProcessing.length;
当前处理
.text(rowsAmount)
.parent().attr('class',rowsAmount>1?“非唯一”:“唯一”);
}
我--;
}
console.profileEnd();
}​
rowsAmount=currentlyProcessing.length;
当前处理
.text(rowsAmount)
.parent().attr('class',rowsAmount>1?“非唯一”:“唯一”);
toCheck=toCheck.not(当前处理);
}
}

$(“#binning tbody”)。儿童('tr')
-为什么不
$(“#binning tbody>tr”)
?谢谢。它确实更干净,但没有明显的性能改进。谢谢,vucetica。桌子是动态的;它通过ajax调用反复追加。无法直接访问数据,因此它需要来自表@mightyuhu建议将数据提取到散列中,然后使用它
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);

    });

}
$(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';
    });            

}​
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);        
    };            
}​
$(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 );
    }
}