未捕获的TypeError - 在对象数组中组合和删除(拼接)重复项时

时间:2014-06-15 17:32:25

标签: javascript arrays

我有一个对象数组,每个对象都有许多不同的键,但最重要的是如下所示......

productArray = [{
  id: 123,
  name 'Sony TV',
  price: 500,
  stock: 123
},
{
  id: 127,
  name 'Sharp TV',
  price: 750,
  stock: 230
},
{
  id: 123,
  name 'Sony TV',
  price: 500,
  stock: 77
}]

显然这个数字很大(比如100个产品)......现在我希望将我所拥有的任何副本(例如产品名称' Sony TV' - 所以我的对象中只有一条记录)数组和库存水平相结合,我也希望得到最高的价格。我写了一个嵌套的循环,通过对象数组,然后在第二个数组检查项目是否有相同的ID,如果我添加库存水平在一起,取最高价格然后从巢循环中删除副本(因为一个项目可能出现两次以上,实际上有些项目可能会出现5或6次)。还有一些其他业务规则,但这些不是&#39现在很重要。这是我的循环代码...

for (i = 0; i < productArray.length; i++) {

        // check if duplicate... second loop
        for (j = productArray.length - 1; j >= 0; j--) {

            if (productArray[i].id === productArray[j].id && productArray[i].id !== undefined) {
                // overwrite, update and combine values... e.g
                console.log('We have a match with ' +  productArray[i].id);
                productArray[i].stock = productArray[i].stock + productArray[j].stock;
                // remove match item from second array
                productArray[j].splice(j, 1);
            }
        }
    }

现在我正在做一些非常错误的事情,因为我得到Uncaught TypeError: undefined is not a function。我很确定这是因为我的逻辑是有缺陷的,我会以错误的方式解决这个问题。有人可以建议一个更好的方法来解释为什么我的逻辑产生错误?非常感谢提前。

3 个答案:

答案 0 :(得分:0)

这是因为每当你从数组中删除元素并且你仍然在运行第二个for循环和i&gt;长度的情况......尝试使用这个......

if ( i < productArray.length && productArray[i].id !== undefined && productArray[i].id === productArray[j].id )

您只有在检查productArray[i].id !== undefined之后才检查productArray[i].id === productArray[j].id是否i>arrayLength productArray[i].id会返回错误

答案 1 :(得分:0)

您正尝试在不是数组的内容上调用.splice()。看来你想要

 productArray.splice(j, 1);

而不是

 productArray[j].splice(j, 1);

另一个问题是你没有检查&#34;重复&#34;你找到的是元素本身。所以你基本上是在清空整个数组,因为每个元素都是自身的重复。

我认为你可以很容易地修复那个改变你的内循环只迭代到第i个元素:

for (j = productArray.length - 1; j > i; j--) {

然而,在&#34; normal&#34;中迭代数组。外循环中的顺序仍然是另一个问题。只需在两个循环中以相反的顺序迭代。

答案 2 :(得分:0)

使用地图存储重复的项目然后从中创建数组会更容易吗?

var products = [{
    name: 'Sony TV',
    stock: 123
  },
  {
    name: 'Sharp TV',
    stock: 230
  },
  {
    name: 'Sony TV',
    stock: 77
  }];

var productsMap = {};

_.each(products, function (item) {
  if (!productsMap[item.name]) {
    productsMap[item.name] = item;
  } else {
    productsMap[item.name].stock += item.stock;
  }
});

// map to array
var result = _.values(productsMap)

没有下划线:

var productsMap = {};

for (var i = 0; i < products.length; i++) {
  var item = products[i];
  if (!productsMap[item.name]) {
    productsMap[item.name] = item;
  } else {
    productsMap[item.name].stock += item.stock;
  }
}

var result = [];
for (var name in productsMap) {
  result.push(productsMap[name]);
}