防止从购物车中删除重复的产品

时间:2019-03-26 21:22:51

标签: javascript reactjs filter

我目前正在为我的投资组合构建一个电子商务商店应用,而我处于以下情况。

用户选择一个项目并将其添加到购物车,然后他们再次将同一项目添加到购物车。现在,当他们想要删除一项时,所有相同的项都将被删除。我当前正在使用过滤器方法,显然过滤器方法正在完成它的工作。

有人可以告诉我如何从购物车中删除一种产品,而不删除其所有类型吗?

谢谢您的时间。

这是我要过滤的数组的示例。

    @Test
    // Test Case # 1: User can login successfuly
    //

    public void Login() throws Exception {
        // -- Setup
        driver.get(constants.URL);
        Assert.assertTrue("Error: Title is '" + driver.getTitle() + "', and should be company name Sign-on", driver.getTitle().startsWith("company name"));

        // -- Test

        driver.findElement(By.id("login")).sendKeys("username");

        driver.findElement(By.id("password")).sendKeys("password");

        driver.findElement(By.xpath("//*[@id=\"loginbox\"]/center[2]/input")).click();

        Assert.assertTrue("Error: Title is '" + driver.getTitle() + "', and should be Country Name | TolaActivity", driver.getTitle().contains("asdasd"));

        driver.quit();
    }

}

5 个答案:

答案 0 :(得分:1)

尝试Array.prototype.reduce淘汰多个项目时,可以使用filter

这将为每个选择的项目返回一个带有数组的对象。数组的长度将是每个id的项数。

let items = selectedProducts.reduce((a,v) => {
  a[v.id] ?  a[v.id].push(v) : a[v.id] = [v];
  return a;
}, {});

更紧凑的版本:

selectedProducts.reduce((a,v)=>(a[v.id]?a[v.id].push(v):a[v.id]=[v],a),{});

let selectedProducts = [
{
  id: 12,
  sku: 12064273040195392,
  title: "Cat Tee Black T-Shirt",
  availableSizes: ["XS", "S"],
  style: "Black with custom print",
  price: 10.9,
  imgUrl: 'photo1',
  currencyId: "GBP",
  currencyFormat: "£",
  isFreeShipping: true
},
{
  id: 13,
  sku: 51498472915966370,
  title: "Dark Thug Blue-Navy T-Shirt",
  availableSizes: ["M"],
  style: "Front print and paisley print",
  price: 29.45,
  imgUrl: 'photo2',
  currencyId: "GBP",
  currencyFormat: "£",
  isFreeShipping: true
},
{
  id: 12,
  sku: 12064273040195392,
  title: "Cat Tee Black T-Shirt",
  availableSizes: ["XS", "S"],
  style: "Black with custom print",
  price: 10.9,
  imgUrl: 'photo1',
  currencyId: "GBP",
  currencyFormat: "£",
  isFreeShipping: true
} ];

let items = selectedProducts.reduce((a,v) => {
a[v.id] ?  a[v.id].push(v) : a[v.id] = [v];
return a;
}, {});

console.log(items);

答案 1 :(得分:1)

您似乎正在尝试删除数组中某项的首次出现。 我建议您使用indexOf和splice方法尝试类似的事情。

function removeFromCart ( sku ) {
  const index = selectedProducts.indexOf( sku );
  selectedProducts.splice( index, 1 ); 
}

最好将splice和indexOf一起使用,因为javascript会为您就地进行删除,而无需创建累加器(当您使用reduce时)。代码也更简单易读。

时间复杂度-O(n) 空间复杂度-O(1)

您可以使用化简器解决问题,但必须创建一个对象来存储结果,从而将空间复杂度提高到O(n)

let selectedProducts = [
    {
      id: 12,
      sku: 12064273040195392,
      title: "Cat Tee Black T-Shirt",
      availableSizes: ["XS", "S"],
      style: "Black with custom print",
      price: 10.9,
      imgUrl: 'photo1',
      currencyId: "GBP",
      currencyFormat: "£",
      isFreeShipping: true
    },
    {
      id: 13,
      sku: 51498472915966370,
      title: "Dark Thug Blue-Navy T-Shirt",
      availableSizes: ["M"],
      style: "Front print and paisley print",
      price: 29.45,
      imgUrl: 'photo2',
      currencyId: "GBP",
      currencyFormat: "£",
      isFreeShipping: true
    },
    {
      id: 12,
      sku: 12064273040195392,
      title: "Cat Tee Black T-Shirt",
      availableSizes: ["XS", "S"],
      style: "Black with custom print",
      price: 10.9,
      imgUrl: 'photo1',
      currencyId: "GBP",
      currencyFormat: "£",
      isFreeShipping: true
    } ];

    const index = selectedProducts.indexOf( 12064273040195392 );
    selectedProducts.splice( index, 1 );

    console.log(selectedProducts);

答案 2 :(得分:0)

也许您可以找到数组中第一项的索引,并根据索引从数组中删除该项。一个例子:

var selectedProducts = [
{
  id: 12,
  sku: 12064273040195392,
  title: "Cat Tee Black T-Shirt",
  availableSizes: ["XS", "S"],
  style: "Black with custom print",
  price: 10.9,
  imgUrl: 'photo1',
  currencyId: "GBP",
  currencyFormat: "£",
  isFreeShipping: true
},
{
  id: 13,
  sku: 51498472915966370,
  title: "Dark Thug Blue-Navy T-Shirt",
  availableSizes: ["M"],
  style: "Front print and paisley print",
  price: 29.45,
  imgUrl: 'photo2',
  currencyId: "GBP",
  currencyFormat: "£",
  isFreeShipping: true
},
{
  id: 12,
  sku: 12064273040195392,
  title: "Cat Tee Black T-Shirt",
  availableSizes: ["XS", "S"],
  style: "Black with custom print",
  price: 10.9,
  imgUrl: 'photo1',
  currencyId: "GBP",
  currencyFormat: "£",
  isFreeShipping: true
} ];


const index = selectedProducts.findIndex(obj => obj.id == 12);
selectedProducts.splice(index, 1);
console.log(selectedProducts);

答案 3 :(得分:0)

您需要为购物车中的每个商品分配唯一的标识符。

例如,当您向卡中添加“ newItem”时:

newItem['uniqueItemId'] = {UniqueIdentifier};
selectedProducts.push(newItem);

这将使您可以访问对象上的uniqueItemId,现在您可以按此值进行过滤,以便仅删除所需的项目:

selectedProducts = selectedProducts.filter(item => item.uniqueItemId !== {UniqueIdentifier});

答案 4 :(得分:0)

这里的答案略长,但是它显示了我们如何分配唯一的购物车ID,然后在删除时使用该ID进行过滤。

对于该演示,购物车ID只是一个Date.now(),其值为Millisecs,因此对此应该是唯一的。

我们在添加到购物车期间分配唯一ID: 注意:我们会复制产品。

const addProductToCart = (id) => {
  let product = Object.assign({}, products.find(p => p.id == id));
  product.cartId = Date.now();**
  cart.push(product);
  renderCart();
};

现在,当您单击购物车中的某个物品(删除)时,我们将调用remove方法: 注意:我们使用购物车ID来引用商品,而不是产品ID

const removeFromCart = (cartId) => {
  cart = cart.filter(item => item.cartId != cartId);
  renderCart();
};

下面是一个有效的代码段,显示了工作原理。

let products = [
  {
    id: 1,
    name: "product one"
  },
  {
    id: 2,
    name: "product two"
  },
  {
    id: 3,
    name: "product three"
  }
];

let cart = [];

const renderProduct = (product) => `<li class="product" data-id="${product.id}">${product.name}</li>`;

const renderCartItem = (cartItem) => `<li class="cartItem" data-cart-id="${cartItem.cartId}">${cartItem.name}</li>`;

const renderCart = () => {
  document.querySelector('.cart').innerHTML = cart.map(c => renderCartItem(c)).join('');
};

const addProductToCart = (id) => {
  let product = Object.assign({}, products.find(p => p.id == id));
  product.cartId = Date.now();
  cart.push(product);
  renderCart();
};

const removeFromCart = (cartId) => {
  cart = cart.filter(item => item.cartId != cartId);
  renderCart();
}

document.addEventListener('DOMContentLoaded', () => {
  document.querySelector('.items').innerHTML = products.map(p => renderProduct(p)).join('');
});

document.addEventListener('click', (e) => {
  if(e.target.matches('.product')) {
    addProductToCart(e.target.dataset.id);
  }

  if(e.target.matches('.cartItem')) {
    removeFromCart(e.target.dataset.cartId);
  }

});
<ul class="items"></ul>
    <ul class="cart"></ul>

关于对象引用的一些说明,以及为什么从产品列表移至购物车列表时必须复制对象的原因。

在第一个代码段中,我们添加时没有对象的任何副本。 注意:即使我们将属性添加到cart[0],它实际上也会添加到所有属性。 因为它是reference,实际上数组只是同一对象的pointers

let products = [
  { 
    id: 1,
    name: "one"
  },
  { 
    id: 1,
    name: "one"
  }  
];

let cart = [];

// Add without copy
for(let i=0; i< 3; i++) {
  cart.push(products[0]);
}

// now add an attribute to one cart item
cart[0].cartId = 1;

cart.forEach(item => console.log(item));

所以我们需要在这里使用Object.assign复制对象。这会创建新的实例,因此每个pointer指向不同的object

let products = [
  { 
    id: 1,
    name: "one"
  },
  { 
    id: 1,
    name: "one"
  }  
];

let cart = [];

// Add without copy
for(let i=0; i< 3; i++) {
  cart.push(Object.assign({}, products[0]));
}

// now add an attribute to one cart item
cart[0].cartId = 1;

cart.forEach(item => console.log(item));

将添加到购物车的内容更改为此:

addCartItems = data => {
  copyData = Object.assign({}, data);
  copyData.cartId = Date.now();
  this.setState({
    cartItems: [...this.state.cartItems, copyData]
  });
};