我有一个数组,每分钟更新一次。当我想显示一天时,我希望获得当天每一小时的平均值。
最近一分钟是添加数组的末尾。
//get the last elements from the array
var hours= (this.today.getHours() + 1) * 60
var data = Array.from(this.temps.data)
let lastData = data.slice(Math.max(data.length - hours))
let newData: any
// calculate the average of every hour
for (let i = 0; i < minutes; i++) {
var cut = i * 60
for (let i = cut; i < (cut + 60); i++) {
newData = newData + lastData[i];
let test = newData/60
console.log(test);
}
}
我不知道如何从每60个元素中构成一个数组。 我的目标是获得像这样的数组
avgHour[20,22,30,27,]
我拥有的阵列每分钟更新一次。所以我需要平均每60个元素才能获得一个小时。
数组看起来像这样
data[25,33,22,33]
一周中的每一分钟真是太长了。
这对我有用
var arrays = [], size = 60;
while (arr.length > 0){
arrays.push(arr.splice(0, size));
}
for (let i = 0; i < (arrays.length - 1); i++) {
var sum = 0
for (let b = 0; b < 60; b++) {
sum += arrays[i][b]
}
let avg = sum/60
arr2.push(avg)
}
这只会每60个元素分割一次数组。现在,我可以计算每60个平均值的平均值。 How to split a long array into smaller arrays, with JavaScript
的副本感谢您的帮助!
答案 0 :(得分:1)
您可以按小时减少数据和分组,然后只需映射即可获得每小时的平均值。我正在用一下时间来解析下面的日期,您可以使用任何喜欢的lib / js来做到这一点...
const arr = Array.from({length: 100}, () => ({time: moment().subtract(Math.floor(Math.random() * 10), 'hours'), value: Math.floor(Math.random() * 100)}));
const grouped = [...arr.reduce((a, b) => {
let o = a.get(b.time.get('hour')) || {value: 0, qty: 0};
a.set(b.time.get('hour'), {value: o.value + b.value, qty: o.qty + 1});
return a;
}, new Map)].map(([k, v]) => ({
[k]: v.value / v.qty
}));
console.log(grouped)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script>
答案 1 :(得分:0)
要测量平均值,我需要每60个元素拆分一次数组。 这是我找到的解决方案
//Calculate the average of every 60 elements to get the average of an hour
var arr2: number[] = []
var arr: number[] = []
arr = Array.from(this.temps.data)
var arrays = [], size = 60;
while (arr.length > 0){
arrays.push(arr.splice(0, size));
}
for (let i = 0; i < (arrays.length - 1); i++) {
var sum = 0
for (let b = 0; b < 60; b++) {
sum += arrays[i][b]
}
let avg = sum/60
arr2.push(avg)
}
毕竟我认为获取数组的最后一个元素很愚蠢,因为这是一个更好的解决方案。但是,谢谢您的帮助!
答案 2 :(得分:0)
通过分组然后减少,您可以按照以下步骤进行操作。
function groupBy(list, keyGetter) {
const map = {};
list.forEach((item) => {
const key = keyGetter(item);
if (!map[key]) {
map[key] = [item];
} else {
map[key].push(item);
}
});
return map;
}
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
const now = (new Date()).getTime();
const stepSize = 60000*1;
const withTime = data.reverse().map((x, i) => { return { time: new Date(now - stepSize * i), temp: x } });
const grouped = groupBy(withTime, x => new Date(x.time.getFullYear(), x.time.getMonth(), x.time.getDate(), x.time.getHours()).valueOf());
const avg = Object.entries(grouped).map((x) => {
return {
time: new Date(Number(x[0])),
temp: x[1].map(y => y.temp).reduce((acc, val) => acc + val) * (1.0 / x[1].length)
}
});
console.log(avg);
答案 3 :(得分:0)
我非常喜欢函数式编程库Ramda。 (免责声明:我是它的作者之一。)我倾向于从简单,可重用的功能来思考。
当我想到如何解决此问题时,我是通过Ramda的观点来考虑的。我可能会这样解决这个问题:
const avgHour = pipe(
splitEvery(60),
map(mean),
)
// some random data
const data = range(0, 7 * 24 * 60).map(_ => Math.floor(Math.random() * 20 + 10))
console.log(avgHour(data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {pipe, splitEvery, map, mean, range} = R</script>
我认为这是相当容易理解的,至少在您理解管道创建了一系列函数之后,每个函数都会将其结果传递给下一个。
现在,通常没有理由包括像Ramda这样的大图书馆来解决一个非常简单的问题。但是该版本中使用的所有功能都易于重用。因此,尝试创建自己的这些功能的版本并使它们对其余应用程序可用可能是有意义的。实际上,这就是像Ramda这样的库实际上是如何构建的。
因此,这是一个具有这些功能的简单实现的版本,您可以将它们放在实用程序库中:
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x)
const splitEvery = (n) => (xs) => {
let i = 0, a = []
while (i < xs.length) {a.push(xs.slice(i, i + n)); i += n}
return a
}
const map = (fn) => (xs) => xs.map(x => fn(x))
const sum = (xs) => xs.reduce((a, b) => a + b, 0)
const mean = (xs) => sum(xs) / (xs.length || 1)
const avgHour = pipe(
splitEvery(60),
map(mean)
)
const range = (lo, hi) => [...Array(hi - lo)].map((_, i) => lo + i)
// some random data
const data = range(0, 7 * 24 * 60).map(_ => Math.floor(Math.random() * 20 + 10))
console.log(avgHour(data))