用于删除对象数组中的重复对象的JavaScript总结属性

时间:2014-06-18 16:01:19

标签: javascript arrays json

我现在已经尝试了几天来解决我的问题而且我不能想象我有以下JSON数组(我们称之为jsonData

[
  { "id": 118748, "price":"", "stocklevel": 100,   "instock": false, "pname": "Apple TV" },
  { "id": 118805291, "price":"", "stocklevel": 432,   "instock": true, "pname": "Hitachi TV"},
  { "id": 118801891, "price":"", "stocklevel": 0,   "instock": false, "pname": "Sony TV" },
  { "id": 118748, "price":"", "stocklevel": 2345,   "instock": true, "pname": "Apple TV"},
...

现在我可能在我的JSON数组中有超过100个项目,我想删除具有重复ID的项目,但是将库存水平相加并保留数组中的顺序,这样一行应取代最近出现的那个id。在上面的JSON中,删除了具有“id”:118748的对象的第一个实例,但它的库存级别值传递/添加了具有相同id的对象的下一个实例,因此JSON数组看起来像这样:

[
  { "id": 118805291, "price":"", "stocklevel": 432,   "instock": true, "pname": "Hitachi TV"},
  { "id": 118801891, "price":"", "stocklevel": 0,   "instock": false, "pname": "Sony TV" },
  { "id": 118748, "price":"", "stocklevel": 2445,   "instock": true, "pname": "Apple TV"},
...

我制作了以下代码来删除重复项,但我无法总结库存水平总数,这是我的代码:

function idsAreEqual(obj1, obj2) {
    return obj1.id === obj2.id;
}

function arrayContains(arr, val, equals) {
    var i = arr.length;
    while (i--) {
        if (equals(arr[i], val)) {
            return true;
        }
    }
    return false;
}

function removeDups(arr, equals) {
    var originalArr = arr.slice(0);
    var i, k, len, val;
    arr.length = 0;

    for (i = originalArr.length - 1, len = originalArr.length, k  = originalArr.length - 1 ; i > 0; --i) {
        val = originalArr[i];

        if (!arrayContains(arr, val, equals)) {
            arr.push(val);
        }
    }
}


removeDups(jsonData, idsAreEqual);
jsonData.reverse();

有人可以帮我解决这个问题吗?请注意,我不能使用Underscore,jQuery或任何其他库。

提前非常感谢

1 个答案:

答案 0 :(得分:3)

您可以执行以下操作,这比我认为的实现要简单一些。我还使用forEachreduce,它们是ES5,但应该适用于现代浏览器。如果您正在使用较旧的非ES5兼容浏览器,则可以使用polyfil:

var data = [
  { "id": 118748, "price":"", "stocklevel": 0,   "instock": false, "pname": "Apple TV" },
  { "id": 118805291, "price":"", "stocklevel": 432,   "instock": true, "pname": "Hitachi TV"},
  { "id": 118801891, "price":"", "stocklevel": 0,   "instock": false, "pname": "Sony TV" },
  { "id": 118748, "price":"", "stocklevel": 2345,   "instock": true, "pname": "Apple TV"}
];

function dedup_and_sum(arr, prop) {
    var seen = {},
        order = [];
    arr.forEach(function(o) {
        var id = o[prop];
        if (id in seen) {
            // keep running sum of stocklevel
            var stocklevel = seen[id].stocklevel + o.stocklevel
            // keep this newest record's values
            seen[id] = o;  
            // upid[118805291], stocklevel=432, instock=truedate stocklevel to our running total
            seen[id].stocklevel = stocklevel;
            // keep track of ordering, having seen again, push to end
            order.push(order.splice(order.indexOf(id), 1));
        }
        else {
            seen[id] = o;
            order.push(id);
        }
    });

    return order.map(function(k) { return seen[k]; });
}

// Get unique records, keeping last record of dups
// and summing stocklevel as we go
var unique = dedup_and_sum(data, 'id');
unique.forEach(function(o) {
    console.log("id[%d], stocklevel=%d, instock=%s", o.id, o.stocklevel, o.instock);
});
// output =>
// id[118805291], stocklevel=432, instock=true
// id[118801891], stocklevel=0, instock=false 
// id[118748], stocklevel=2445, instock=true

编辑已更新,以符合我们在评论中讨论的要求。