JavaScript删除对象数组中的重复对象&;对属性求和
几天来,我一直在试图找到解决问题的方法,但我无法想象我拥有以下JSON数组(我们称之为JavaScript删除对象数组中的重复对象&;对属性求和,javascript,arrays,json,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"
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();
有人能帮我解决这个问题吗?请注意,我不能使用下划线、jQuery或任何其他库
提前非常感谢您可以执行以下操作,这比我认为的实现要简单一些。我还使用了
forEach
和reduce
,这两种浏览器都是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
编辑更新以符合我们在评论中讨论的要求。您可以执行以下操作,这比我认为的实现要简单一些。我还使用了
forEach
和reduce
,它们是ES5,但应该适用于现代浏览器。如果您正在使用对于较早的、不兼容ES5的浏览器:
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
编辑更新以符合我们在评论中讨论的要求。感谢您的回答,但是我认为我没有很好地解释我自己……您知道(请注意更新的jsonData)我希望在Json数据中求和库存水平的总和,因此在上面的示例中,我们删除id为118748的第一项,并将库存水平添加到第二项(或相同id的最终出现项),因此,在上述情况下,id:118748的第一次出现被删除,其库存水平被汇总到第二次出现,即2445 OK,因此当您删除DUP时,您希望库存水平是该特定
id
的所有库存水平的运行总和,对吗?我已经更新了问题-我真的很抱歉融合你和解释的东西太糟糕了,应该可以了。我将求和功能移到了dedup
函数中,将其重命名为dedup_和_sum
,这样它就可以使用该id在最近看到的记录上保持一个总的库存水平。这很好,但是定位错误,我想要id[118748]作为out OUTPUTED数组中的最后一项,而不是第一项,数组中的顺序应该是一行,以取代该id的最新出现。但是您所做的是一个很大的帮助,并真正教育了我!感谢您的伟大回答,但我认为我没有很好地解释我自己…您看到了(请注意更新的jsonData)我希望在Json数据中求和库存水平的总和,因此在上面的示例中,我们删除id为118748的第一项,并将库存水平添加到第二项(或相同id的最终出现项),因此,在上述情况下,id:118748的第一次出现被删除,其库存水平被汇总到第二次出现,即2445 OK,因此当您删除DUP时,您希望库存水平是该特定id
的所有库存水平的运行总和,对吗?我已经更新了问题-我真的很抱歉融合你和解释的东西太糟糕了,应该可以了。我将求和功能移到了dedup
函数中,将其重命名为dedup_和_sum
,这样它就可以使用该id在最近看到的记录上保持一个总的库存水平。这很好,但是定位错误,我想要id[118748]要成为out OUTPUTED数组中的最后一项,而不是第一项,数组中的顺序应该是一行来代替该id的最新出现。但是您所做的是一个很大的帮助,并真正教育了我!