【问题标题】:What is a faster way to write this function to delete rows/objects in a table?编写此函数以删除表中的行/对象的更快方法是什么?
【发布时间】:2017-07-31 01:20:34
【问题描述】:

所以,我有这个函数,它在更新后从表中删除元素。这个函数,我们称之为 foo(),接受一个参数。

foo(obj);

此对象 obj 在称为 Array 类型的消息中具有一个子字段。所以,它会看起来像这样:

obj.messages = [...];

此外,在 obj.messages 内部,每个元素都包含一个对象,该对象具有另一个名为 id 的子字段。所以,这看起来像:

obj.messages = [{to:"You",from:"Me",id:"QWERTY12345.v1"}, ...];

现在,除了参数之外,我还有一个活动表也被函数 foo 引用。它使用我称为 oTable 的 dataTable 元素。然后我抓取 oTable 的行并将它们复制到一个名为 theCurrentTable 的数组中。

var theCurrentTable = oTable.$('tr').slice(0);

现在,棘手的地方在于,当我查看 Array theCurrentTable 时,返回的值如下所示。

theCurrentTable = ["tr#messagesTable-item-QWERTY12345_v1", ...];

下面的循环显示了我如何尝试显示问题。虽然它可以工作(看起来),但函数本身可以有超过 1000 条消息,这是一个非常昂贵的函数。它所做的只是检查当前显示的表格是否具有参数中给定的元素,如果不是特定元素,则将其删除。我怎样才能更好地编写这个函数?

var theCurrentTable = oTable.$('tr').slice(0);
var theReceivedMessages = obj.messages.slice(0);

for(var idx = 0; idx < theCurrentTable.length; idx++){ // through display
    var displayID = theCurrentTable[idx].id.replace('messagesTable-item-','').replace('_','.');
    var deletionPending = true;
    for(var x = 0; x < theReceivedMessages.length; x++){
        var messageID = theReceivedMessages[x].id;
        if(diplayID == messageID){
            console.log(displayID+' is safe...');
            deletionPending = false;
        }
    }
    if(deletionPending){
        oTable.fnDeleteRow(idx);
    }
}

【问题讨论】:

    标签: javascript jquery arrays algorithm datatables


    【解决方案1】:

    我想我理解你的问题。您的 &lt;tr&gt; 元素有一个 id 应该与您的消息中的项目 ID 匹配。

    首先你应该从obj参数中提取你需要的消息ID值

    var ids = obj.messages.map(function (m) { return '#messagesTable-item-' + m.id; });
    

    这将为您提供您需要保留的所有行 ID,然后将数组连接在一起以使用 jQuery 选择您不想要的行并删除它们。

    $('tr').not(ids.join(',')).remove();
    

    注意:Array.prototype.map() 函数仅支持 IE9,因此您可能需要使用jQuery.map()

    【讨论】:

    • 这从字面上删除了所有内容...有没有让它更具体?
    • 您确定ids 中的值与您要保留的&lt;tr&gt; 元素的id 属性完全匹配吗? $(ids.join(',')) 会告诉你匹配的内容。如果没有匹配项,它会删除每个&lt;tr&gt;。使用console.log(ids); 查看您创建的内容。而不是.remove() 尝试hide() 这样您仍然可以看到DOM 中的元素。
    【解决方案2】:

    您可以创建一组您拥有的消息 ID 值,以便稍后检测给定 ID 是否在此 Set 中。

    这就是它的样子:

    var theCurrentTable = oTable.$('tr').slice(0);
    var theReceivedMessages = obj.messages.slice(0);
    
    // Pre-processing: create a set of message id values:
    var ids = new Set(theReceivedMessages.map( msg => msg.id ));
    
    theCurrentTable.forEach(function (row, idx) { // through display
        var displayID = row.id.replace('messagesTable-item-','').replace('_','.');
        // Now you can skip the inner loop and just test whether the Set has the ID:
        if(!ids.has(displayId)) {
            oTable.fnDeleteRow(idx);
        }
    });
    

    所以现在时间复杂度不再是 O(nm) -- 其中 n 是消息的数量,而 m 是数量表行数——但是 O(n+m),对于较大的 nm 值可能会产生很大的不同。 p>

    注意事项:

    如果 theCurrentTable 不是真正的数组,那么您可能需要像以前一样使用 for 循环,或者使用 Array.from(theCurrentTable, function ...)

    其次,oTable.fnDeleteRow的实现可能是你需要先删除最后一行,这样idx仍然指向原来的行号。在这种情况下,您应该从末尾开始反转循环。

    【讨论】:

    • 我认为这里有一些语法错误。否则,它可以工作。
    • 是的,我无法测试代码,因为没有指定 oTableobj 的定义。我刚刚更正了一些语法问题,并添加了两个注释以供考虑..
    猜你喜欢
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    相关资源
    最近更新 更多