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

时间:2012-04-02 21:53:36

标签: javascript

我有两个数组。如果用户添加了产品,我们会将其放入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;
    }
}

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

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

9 个答案:

答案 0 :(得分:3)

您可以创建两个列表对象而不是整数数组,并使用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编码的哈希(或map,或者依赖于语言的assoc数组)而不是列表,但这绝对是一种更快的方式删除。

答案 1 :(得分:1)

一个不同的想法是删除一个项目超级快,只是维护一个项目列表,并在每个项目上有一个属性,以确定它是否被删除。

然后要移除一个项目,只需设置它的属性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
});

答案 2 :(得分:1)

使用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;
}

答案 3 :(得分:1)

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

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

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

    显然需要循环,并且使用循环不会降低效率。我的建议是避免使用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"
    }
    

答案 4 :(得分:0)

可能会弄错,但不是你的代码只是和

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

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

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

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

请注意,此系统的设计存在一个可能的缺陷:客户删除项目并稍后将其添加回来是合理的。根据您所追踪的内容,您可能需要特殊情况。

答案 7 :(得分:0)

我会这样做的:

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

答案 8 :(得分:0)

在大多数浏览器中,

排序可能出乎意料地得到了优化。 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)
);