JavaScript有效地计算给定间隔内的平均值



我有两个数组,其中一个表示数据,另一个表示间隔。两者都经过排序,并且它们的起始值和结束值匹配。我通过嵌套的for循环来计算给定间隔中数据点的平均值。结果,我得到了每个间隔一个数据值。对于较小尺寸的阵列,<100-500长度,这些线性循环完成了工作,然而,这种方法在数千个数据点上成为了一个问题。如有任何建议,我们将不胜感激。

请参阅下面的简化代码,并在末尾链接到JSfiddle

var TimelineArray = [0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100],
	DataArray = [0, 2, 4, 5, 8, 11, 19, 22, 24, 25, 30, 31, 38, 39, 51, 56, 57, 58, 59, 64, 74, 76, 89, 91, 92, 94, 98, 100],
	DataArrayA = [];
for (i = 0; i < TimelineArray.length-1; i++) {
	var dataPointsInGivenTimeInterval = [];
	for (j = 0; j < DataArray.length; j++) {
		if (DataArray[j] > TimelineArray[i] && DataArray[j] <= TimelineArray[i+1]) {
			dataPointsInGivenTimeInterval.push(DataArray[j]);
		}
	};
	if (dataPointsInGivenTimeInterval.length == 0) {
		DataArrayA.push(null);
	}
	else {
		var sumOfdataPoints = null;
		for (k = 0; k < dataPointsInGivenTimeInterval.length; k++) {
			sumOfdataPoints += dataPointsInGivenTimeInterval[k];
		}
		var avg = sumOfdataPoints / dataPointsInGivenTimeInterval.length;
		DataArrayA.push(avg);
	}
} // end for
console.log(TimelineArray);
console.log(DataArrayA);
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

控制台输出为

[0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100]
[4.75, 15, 25.25, 36, null, 56.2, 64, 75, 89, 95]

以下是JSfiddle的代码-计算给定区间的平均值

由于数组是排序的,因此可以根据时间线和数据的大小进行线性排序:

var timeline = [0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100],
    data = [0, 2, 4, 5, 8, 11, 19, 22, 24, 25, 30, 31, 38, 39, 51, 56, 57, 58, 59, 64, 74, 76, 89, 91, 92, 94, 98, 100];
var averages = new Array(timeline.length - 1);
for (var i = 0, j = 0; i < timeline.length; i++) {
  var sum = 0,
      items = 0;
  for (; data[j] <= timeline[i]; j++) {
    sum += data[j];
    ++items;
  }
  if(i) averages[i-1] = sum / items;
}
console.log(averages);
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

您不需要在每次迭代中从头开始重新扫描DataArray

var TimelineArray = [0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100];
var DataArray = [0, 2, 4, 5, 8, 11, 19, 22, 24, 25, 30, 31, 38, 39, 51, 56, 57, 58, 59, 64, 74, 76, 89, 91, 92, 94, 98, 100];
var res = [], pos = 0;
TimelineArray.forEach(function(v, i) {
  for(var sum = 0, n = 0; DataArray[pos] <= v; n++) {
    sum += DataArray[pos++];
  }
  i && res.push(n ? sum / n : null);
});
console.log(res);

不确定它是否会更快,但这里有一个不同的方法:

var TimelineArray = [0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100],
DataArray = [0, 2, 4, 5, 8, 11, 19, 22, 24, 25, 30, 31, 38, 39, 51, 56, 57, 58, 59, 64, 74, 76, 89, 91, 92, 94, 98, 100],
DataArrayA = [];
  
function avg(arr){
  if(arr!= null && arr.length > 0)
    return arr.reduce(function(a, b){ return a+b;}, 0) / arr.length;
  return null;
}
for(var i = 0; i < TimelineArray.length-1; i++){
  var interval = [TimelineArray[i], TimelineArray[i+1]];
  var data = DataArray.filter(function(a){ return a > interval[0] && a <= interval[1]});
  DataArrayA.push(avg(data));
}
console.log(DataArrayA);

编辑1:删除一个循环。

最新更新