2016-08-04 61 views
1

我有兩個數組,其中一個表示數據,另一個表示數據 - 間隔。兩者都進行排序並且其開始和結束值相匹配。我通過嵌套for循環計算給定時間間隔內數據點的平均值。結果,我最終得到每個區間的一個數據值。對於尺寸較小的陣列,長度爲100-500,這些線性迴路可以完成這項工作,但是,這種方法成爲數千個數據點的問題。任何建議將不勝感激。JavaScript數組 - 有效計算給定時間間隔內的平均值

請末見下面的簡化代碼以鏈接到的jsfiddle

var TimelineArray = [0, 10, 20, 30, 40, 40, 60, 70, 80, 90, 100], 
 
\t 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], 
 
\t DataArrayA = []; 
 

 
for (i = 0; i < TimelineArray.length-1; i++) { 
 
\t var dataPointsInGivenTimeInterval = []; 
 
\t for (j = 0; j < DataArray.length; j++) { 
 
\t \t if (DataArray[j] > TimelineArray[i] && DataArray[j] <= TimelineArray[i+1]) { 
 
\t \t \t dataPointsInGivenTimeInterval.push(DataArray[j]); 
 
\t \t } 
 
\t }; 
 
\t if (dataPointsInGivenTimeInterval.length == 0) { 
 
\t \t DataArrayA.push(null); 
 
\t } 
 
\t else { 
 
\t \t var sumOfdataPoints = null; 
 
\t \t for (k = 0; k < dataPointsInGivenTimeInterval.length; k++) { 
 
\t \t \t sumOfdataPoints += dataPointsInGivenTimeInterval[k]; 
 
\t \t } 
 
\t \t var avg = sumOfdataPoints/dataPointsInGivenTimeInterval.length; 
 
\t \t DataArrayA.push(avg); 
 
\t } 
 
} // 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代碼 - calculating average values for given intervals

+0

我已經從陣列得到的平均值,是否可以幫助一個簡單的解決方案?還有一個複雜的功能將這些功能添加到數學對象中? – SpYk3HH

+0

https://github.com/JDMcKinstry/Math.Extensions使用'Math.average([0,10,20,30,40,60,70,80,90,100])''結果在'49.09090909090909' – SpYk3HH

+0

TimelineArray的元素之間的間隔是否始終相同(本例中爲10)? – 10100111001

回答

2

由於陣列進行排序,你可以線性方面做的時間線的大小和數據:

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; 
 
}

0

不知道這將是任何更快,但這裏有一個裂縫它以不同的方式:

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:刪除一個循環。

1

從每次迭代開始就不需要重新掃描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);

+0

我喜歡在每次迭代時從頭開始掃描整個數據數組的想法。最後的部分呢?我相信同樣的想法可以應用於同一個數據數組的結束標籤。一旦數據值變得比循環中給定時間間隔的右邊緣大,那麼很明顯數據數組的其餘部分也會變得更大。所以他們也可以被忽略。 – user2217057

+0

請注意,@Oriol使用非常類似的解決方案從一開始就沒有重新掃描過10分鐘。 ^^不知道在最後部分理解你的想法。它不適用於你的示例數據集,因爲兩個數組都以100結尾,對嗎? – Arnauld

+0

好吧,實際上它已經存在了,我只是錯過了它,在@ Oriol的代碼中,嵌套循環的條件做了我所提及的(; data [j] <= timeline [i]; j ++)。你的代碼也一樣。非常感謝! – user2217057