使用Underscore.js合并/组合和求和数组项
Using Underscore.js To Merge/Combine and Sum Array Entries
我有两个JSON对象数组,我希望将它们合并/组合在一起,然后将任何匹配项的数量相加。
两个阵列都包含相同的结构,其中一个表示需要使用的设备列表。。。
var required = [
{ SerialisedEquipment: { SerialNo: "ser855212" }, Type: undefined, Serialised: true, Quantity: 1 },
{ SerialisedEquipment: { SerialNo: "ser288945" }, Type: undefined, Serialised: true, Quantity: 1 },
{ SerialisedEquipment: undefined, Type: { ItemId: "itm71770" }, Serialised: false, Quantity: 5 },
{ SerialisedEquipment: undefined, Type: { ItemId: "itm11025" }, Serialised: false, Quantity: 2 }];
另一个表示实际已经使用的设备的列表。
var used = [
{ SerialisedEquipment: { SerialNo: "ser663033" }, Type: undefined, Serialised: true, Quantity: 1 },
{ SerialisedEquipment: { SerialNo: "ser288945" }, Type: undefined, Serialised: true, Quantity: 1 },
{ SerialisedEquipment: undefined, Type: { ItemId: "itm71770" }, Serialised: false, Quantity: 2 }];
我可以访问undercore.js,并一直在尝试使用_.groupBy和_.reduce方法来尝试获得我想要的结果,但没有成功。我希望实现的结果是:
var result = [
{ SerialisedEquipment: { SerialNo: "ser663033" }, Type: undefined, Used: 1, Expected: 0, Remaining: 0 },
{ SerialisedEquipment: { SerialNo: "ser288945" }, Type: undefined, Used: 1, Expected: 1, Remaining: 0 },
{ SerialisedEquipment: { SerialNo: "ser855212" }, Type: undefined, Used: 0, Expected: 1, Remaining: 1 },
{ SerialisedEquipment: undefined, Type: { ItemId: "itm71770" }, Used: 2, Expected: 5, Remaining: 3 },
{ SerialisedEquipment: undefined, Type: { ItemId: "itm11025" }, Used: 0, Expected: 2, Remaining: 2 }];
我也一直在研究下划线提供的一些数组方法,但我不确定如何使用这些方法来指定合并的条件。有人对实现这一点的最佳方法有什么建议吗?
更新
我已经设法获得了两个阵列的合并列表,删除了重复项。。。
// Split based on the serialised flag - so I know to look at either the serialNo or Type property
var isSerialised = _.groupBy(required, function (equip) {
return equip.Serialised;
});
// Get all the required serialised equipment that is not already in the used list
var serialised = _.filter(isSerialised[true], function (value) {
return (!_.some(used, function (equip) {
return equip.SerialisedEquipment && equip.SerialisedEquipment.SerialNo == value.SerialisedEquipment.SerialNo;
}));
});
// Get all the required types that are not already in the used list
var types = _.filter(isSerialised[false], function (value) {
return (!_.some(used, function (equip) {
return equip.Type && equip.Type.ItemId == value.Type.ItemId;
}));
});
// Combine the equipment that is not in the list with the equipment that is in the list
var result = _.union(used, serialised, types);
我认为现在只是一个循环通过这个结果列表和所需设备列表,并根据序列号或类型总结匹配的设备的情况。
有时想要使用库会让你错过更简单的算法:
var resultsById = {};
function getTemporaryId(value) {
return value.SerialisedEquipment ? value.SerialisedEquipment.SerialNo : value.Type.ItemId;
}
function getResultForValue(value) {
var id = getTemporaryId(value);
if(!resultsById[id]) {
resultsById[id] = {
SerialisedEquipment: value.SerialisedEquipment,
Type: value.Type,
Used: 0,
Expected: 0,
Remaining: 0
};
}
return resultsById[id];
}
_.each(required, function(value) {
var result = getResultForValue(value);
result.Expected += value.Quantity;
result.Remaining += value.Quantity;
});
_.each(used, function(value) {
var result = getResultForValue(value);
result.Used += value.Quantity;
result.Remaining = Math.max(result.Remaining - value.Quantity, 0);
});
var merged = _.values(resultsById);
如果你真的想使用很多下划线,你可以使用这个解决方案:
var requiredValues = _.map(required, (function(value){
//maybe want to clone value? value = _.clone(value);
value.Used = 0;
value.Expected = value.Quantity;
return value;
}));
var usedValues = _.map(used, (function(value){
//maybe want to clone value? value = _.clone(value);
value.Used = value.Quantity;
value.Expected = 0;
return value;
}));
var mergedValues = _.chain(requiredValues.concat(usedValues))
.groupBy(function(value){
return value.SerialisedEquipment ? value.SerialisedEquipment.SerialNo : value.Type.ItemId;
})
.map(function(values) {
var memo = {
SerialisedEquipment: values[0].SerialisedEquipment,
Type: values[0].Type,
Used: 0,
Expected: 0,
Remaining: 0
};
return _.reduce(values, function(memo, value) {
memo.Used += value.Used;
memo.Expected += value.Expected;
memo.Remaining = Math.max(memo.Expected - memo.Used, 0);
return memo;
}, memo)
})
.values()
.value();
您只需使用Array.concat()方法:
var result = required.concat(used);
它会让你合并。
编辑
不过,如果你想使用不理想的方法_.union(arr1,arr2)适合你!
相关文章:
- 如何按对象数组进行分组和求和
- 求和d3对象数组上的元素
- 如何使用数组减少来求和对象属性长度,不带类型
- 求和并组织数组
- 用于从包含最大求和的整数数组中提取子数组的算法
- JavaScript 对多维数组元素值求和
- 合并两个对象数组,同时对特定键求和
- 对关联数组键值求和并按键分组
- 如何在 AngularJS ng-repeat中对 Json 数组值求和
- 数组中对象的值求和
- 在对象数组中对具有相同对象属性 B 的 JavaScript 对象属性 A 值求和
- 只是尝试对 JavaScript 数组的 2 个特定元素求和
- 对 JavaScript 数组重复值求和
- 如何对文本框数组中存储的值求和
- 为什么数组和对象([ ] + {})的求和是javascript中的一个字符串
- 如何合并两个对象数组,并在 JavaScript 中对重复对象键的值求和
- JS-数组的求和元素
- 对对应于另一个数组的数组的值求和
- 如何使用Ramda通过索引对n数组求和
- 对JSON数组响应中的值求和