javascript - 随着时间的推移对两个有序的累积对象值数组求和
问题描述
我试图弄清楚如何对两个数组的累积值求和,这看起来很简单,但复杂的是:其中一个数组可能缺少日期。
当一个有日期值而另一个没有时,我们将一个数组中存在的值与另一个数组的日期的最后一次看到(先前)值相加(我给出的示例更好地说明了这一点) .
例如,给定两个对象数组,其中 data2 中有一个 data1 没有的日期值:
var data1 = [
{date: "30-08-2019", value: 1},
{date: "03-09-2019", value: 2},
{date: "04-09-2019", value: 3}
]
var data2 = [
{date: "30-08-2019", value: 1},
{date: "02-09-2019", value: 2},
{date: "03-09-2019", value: 3},
{date: "04-09-2019", value: 4}
]
我希望将这两者(data1 + data2)相加的结果是:
var result = [
{date: "30-08-2019", value: 2}, //{date: "30-08-2019", value: 1} + {date: "30-08-2019", value: 1}
{date: "02-09-2019", value: 3}, //{date: "30-08-2019", value: 1} + {date: "02-09-2019", value: 2}
{date: "03-09-2019", value: 5}, //{date: "03-09-2019", value: 2} + {date: "03-09-2019", value: 3}
{date: "04-09-2019", value: 7} //{date: "04-09-2019", value: 3} + {date: "04-09-2019", value: 4}
]
由于两个数组都是有序的,我认为的方法是用更多数据循环数组,并将其与数据较少的数组的值相加,跟踪较小数据给出的最后日期值是什么,如下所示:
for(let i = 0; i < biggerData.length; i++){
//both have values for a date that exists the in bigger date array, so we sum them together
if(smallerData[i][biggerData[i].date]){
biggerData[i].value+=smallerData[i][biggerData[i].date];
lastValue = smallerData[i][biggerData[i].date];
//array with less data has a missing date, then sum the last saved value it gave
}else{
biggerData[i].value+=lastValue;
}
}
这种方法有一个问题,如果较小的数组有一个较大的数组没有的日期怎么办?在这种情况下,该值不会添加到最终结果中。
当比这更进一步时,我开始像之前展示的那样循环一个数组,然后循环另一个数组以获取丢失的日期,但这似乎太复杂且效率低下。我很确定有一个解决方案可以在一个循环中执行此操作(甚至根本不使用循环)。
我在问是否有人可以为此找到更好的解决方案,我正在用 JavaScript 做这个。
解决方案
我使用了一堆辅助变量并将日期转换为易于排序的格式。按时间顺序遍历所有现有日期可以很容易地跟踪每个数组的累积值。排序是低效的部分,因为其余部分具有线性复杂性。您可以利用两个数组都已排序的事实来优化排序,但我懒得在这里这样做:)
// Turn '30-08-2019' into '2019-08-30'
const getSortableDate = (dateString) => dateString.split('-').reverse().join('-');
// Enable direct lookup of values
const mapDatesToValues = (data) => {
const dates = {};
data.forEach((item) => {
dates[getSortableDate(item.date)] = item.value;
});
return dates;
};
// Source data
const data1 = [
{date: "30-08-2019", value: 1},
{date: "03-09-2019", value: 2},
{date: "04-09-2019", value: 3}
];
const data2 = [
{date: "30-08-2019", value: 1},
{date: "02-09-2019", value: 2},
{date: "03-09-2019", value: 3},
{date: "04-09-2019", value: 4}
];
// values for direct lookup
const dates1 = mapDatesToValues(data1);
const dates2 = mapDatesToValues(data2);
// Chronological order for all existing dates
const allDatesOrdered = Object.keys({ ...dates1, ...dates2 }).sort();
// Helper variables:
let acc1 = 0; // Accumulated value while iterating through data1
let acc2 = 0; // Accumulated value while iterating through data2
let existsIn1;
let existsIn2;
let value1; // Current value while iterating through data1
let value2; // Current value while iterating through data2
allDatesOrdered.forEach((date) => {
existsIn1 = dates1.hasOwnProperty(date);
existsIn2 = dates2.hasOwnProperty(date);
value1 = dates1[date];
value2 = dates2[date];
// Remember accumulated values
if (existsIn1) {
acc1 = value1;
}
if (existsIn2) {
acc2 = value2;
}
if (existsIn1 && existsIn2) {
console.log('sum for', date, 'is', value1 + value2, '(found in both arrays)');
} else {
if (existsIn1) {
console.log('sum for', date, 'is', value1 + acc2, '(only found in data1)');
} else {
console.log('sum for', date, 'is', value2 + acc1, '(only found in data2)');
}
}
});
推荐阅读
- cluster-computing - AWS Cloudformation 和 Autoscaling 不断将实例放置在同一个 AZ
- python - 为什么 json.dumps() 和 json.loads() 会产生 unicode 字符串?
- gradle - 我可以将 OSGi Mocks 与声明式服务注释一起使用吗
- react-native - React Native - React Apollo - 数据道具未定义
- vbscript - wscript.exe 停止使用自定义协议
- python - Python Pandas 滚动意味着 DataFrame 构造函数未正确调用
- grep - 让grep按时间顺序搜索多个文件
- javascript - 如何使用精美的 box 3 库显示加载图标
- python - 没有扩展名的文件的条件,或者还查看文件名 - Python
- javascript - 功能优化,用非重音元音替换重音元音