繁体   English   中英

从数组中删除项目的最有效方法?

[英]Most efficient way to remove an item from array?

我有两个 arrays。如果用户添加了一个产品,我们将其放入 ProductArray。 如果他们删除了该产品,我们将其添加到 ProductArrayRemove 数组并将其从产品数组中删除。 (我们需要知道已添加的产品以及已删除的产品。这需要冗余。)

ProductArray = JSON.parse(ProductArray);
ProductArrayRemove = JSON.parse(ProductArrayRemove);

当我将项目添加到数组时,我只是这样做:

 ProductArray.push(ItemID);
 ProductArrayRemove.push(ItemID);

但是当我删除它时,我必须这样做:

var len = ProductArray.length;
for (i = 0; i < len; i++) {
    ProductID = ProductArray[i];
    if (ProductID == ItemID) {
        ProductArray.splice(i,1);
        break;
    }
}

似乎应该有更好的方法来完成这项任务。

是否有更有效的方法从数组中删除单个项目(始终是整数)?

您可以创建两个列表对象而不是整数数组,并使用delete删除项目:

// removing an item
function RemoveProduct(ItemID) {
    delete ProductsAdded[ItemID];
    ProductsRemoved[ItemID] = ItemID;
}

// adding an item
function AddProduct(ItemID) {
    delete ProductsRemoved[ItemID];
    ProductsAdded[ItemID] = ItemID;
}

现在,这需要在服务器端进行一些额外的修改,因为它应该发送json编码的散列(或映射,或者依赖于语言的assoc数组)而不是列表,但这绝对是一种更快的删除方法。

删除项目的一个不同的想法是只保留一个项目列表,并在每个项目上具有一个属性,以确定它是否被删除。

然后删除一个项目,你只需要设置它的属性obj.removed = true

再次添加它,您只需更改该属性的值。

要仅迭代添加的项,您只需跳过具有.removed == true属性的项。 要仅迭代已删除的项目,您可以反过来。 这里有几个迭代器:

ProductArray.iterateAdded = function(fn) {
    for (var i = 0; i < this.length; i++) {
        if (!this[i].removed) {
            if (fn.call(this, i, this[i]) === false) {
                return;
            }
        }
    }
}

ProductArray.iterateRemoved = function(fn) {
    for (var i = 0; i < this.length; i++) {
        if (this[i].removed) {
            if (fn.call(this, i, this[i]) === false) {
                return;
            }
        }
    }
}

ProductArray.getSubLength = function(removed) {
    var cnt = 0;
    for (var i = 0; i < this.length; i++) {
        if (removed == this[i].removed) {
            ++cnt;
        }
    }
    return(cnt);
}

而且,你会像这样使用它们:

ProductArray.iterateAdded(function(i, val) {
   // this is the array
   // i is the index we are iterating
   // val is the array element we are iterating this[i]
   // put code here
});

使用Array方法indexOf-值得你需要额外的代码来向旧的和营养不良的浏览器解释它,以便在像你这样的代码中使用它。

var i= ProductArray.indexOf(ProductID);
if(i> -1) ProductArray.splice(i, 1);

//这个垫片大约平均:

if(!Array.prototype.indexOf) Array.prototype.indexOf= function(what, i){
    if(!i || typeof i!= 'number') i= 0;
    var L= this.length;
    while(i< L){
        if(this[i]=== what) return i;
        ++i;
    }
    return -1;
}

首先,通常会误认为调用函数比编写10行代码更有效。 我们大多数人都不认为函数实际上是做什么以及函数中有多少行。 例如: indexOf不使用循环或其他变量,则无法实现indexOf

在你的情况下,你使用push添加一个元素,它实际上在数组的末尾附加一个元素。 所以很简单,再向阵列添加一个内存位置。 但是当你删除一个元素时,你将它从数组中的任何索引中删除。 所以涉及的步骤是

  1. 找到元素的索引
  2. 从该索引中删除元素
  3. 在删除的索引后调整所有元素的索引

显然需要循环,并且使用循环不会降低效率。 我的建议是避免使用splice (因为你已经开始循环)并仅使用你的循环删除元素 - 做一些如下所示的事情

var len = ProductArray.length;
for (i = 0; i < len; i++) {
    ProductID = ProductArray[i];
    if (ProductID == ItemID && i != len-1) {
        ProductArray[i] = ProductArray[i+1];
        ProductArray[i+1] = ItemID;
    }else if(i == len-1){
        ProductArray.length = i;
    }
}

您可以通过将其添加到protoype使其成为数组的函数

Array.prototype.removeItem = function (itemID){
    // put the code here replacing "ProductArray" with "this"
}

Array.prototype.filter()应该可以解决问题。 参考

Array.filter()遍历每个数组元素(本例为product )并根据您的需要返回一个新的修改后的数组(本例返回一个没有删除产品的数组)

它看起来像这样:

  ProductArray = ProductArray.filter(function(product) {
        return product !== ItemID
    })

product是 ProductArray 中的每个数组元素。

您甚至可以使用箭头 function使其更小,这几乎与function()相同,但更紧凑和有限。

  ProductArray = ProductArray.filter(product => product !== ItemID)

现在 ProductArray 没有删除的产品,它是一个单线解决方案

可能会弄错,但不是你的代码只是做同样的事情

ProductArray.splice(ProductArray.indexOf(ItemID),1);

(没有经过测试和编写,但据我所知,这应该可以正常工作,但如果你有多个ItemID项,它将不起作用)

不需要。这样的操作必须花费线性时间来找到要移除的元素(假设项目没有以任何方式排序)并向后移动后续元素。 可以像其他答案所建议的那样清理代码。

为什么不使用对象,其中键是产品ID#s,并且值包含您想要的任何元数据(例如,当删除发生时,在什么网页上等;它甚至可以是任意的)。

var added = {432215: {...}, 432676: {...}};
var removed = {432215: {...}};

如果你愿意修改一些东西,这就是你要求的最有效的方法。 然而,你的问题“什么是最有效的方式......”并不合理,因为用户不太可能在他的购物车顶部有超过100件物品。 即使你有一个O(N ^ 2)算法,你也不会看到问题,直到1000项。 所以只需使用最容易编码的方法。

请注意,该系统的设计存在一个可能的缺陷:客户移除物品并在以后添加物品是合理的。 根据您的跟踪记录,您可能需要特殊情况。

我会这样做的:

var itemId = 6;
var products = [1,3,5,6,7];
var removedProducts = new Array();
removedProducts.push(
   products.splice(products.indexOf(itemId), 1)
);

在大多数浏览器中,Sort可能出乎意料地得到了很好 Pop通常也非常快,因为堆栈的概念始于汇编。 能够定义排序函数真的很强大。 大多数情况下,虽然我得到的印象是你喜欢它,但我认为这更容易使用。

Array.prototype.numFindPop = function(id){
    this.sort( 
        function(a,b){
            if(a === id){ return -1; }//keeps moving id to the right when found
        }
    );

    return this.pop();

}

所以在你的情况下:

//remove
ProductArrayRemove.push(
    ProductArray.numFindPop(35)
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM