Last active
August 29, 2015 14:07
-
-
Save shimondoodkin/f274d6e17c66a8b72779 to your computer and use it in GitHub Desktop.
rolling/running min in readable javascript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this grown up to a module - | |
// https://github.com/shimondoodkin/efficient-rolling-stats |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//rolling min max in minified javascript | |
// from http://stackoverflow.com/a/12195098/466363 | |
// https://gist.github.com/shimondoodkin/f274d6e17c66a8b72779 | |
function RollingMin(e){function s(e){if(t.length!==0&&t[0]<=r-i){t.shift();n.shift()}while(n.length!==0&&n[n.length-1]>e){t.pop();n.pop()}t.push(r);n.push(e);r++;return n[0]}var t=[],n=[],r=0,i=e;return s} | |
function RollingMax(e){function s(e){if(t.length!==0&&t[0]<=r-i){t.shift();n.shift()}while(n.length!==0&&n[n.length-1]<e){t.pop();n.pop()}t.push(r);n.push(e);r++;return n[0]}var t=[],n=[],r=0,i=e;return s} | |
function RollingMinIndex(e){function i(e,i){if(t.length!==0&&t[0]<=i-r){t.shift();n.shift()}while(n.length!==0&&n[n.length-1]>e){t.pop();n.pop()}t.push(i);n.push(e);return n[0]}var t=[],n=[],r=e;return i} | |
function RollingMaxIndex(e){function i(e,i){if(t.length!==0&&t[0]<=i-r){t.shift();n.shift()}while(n.length!==0&&n[n.length-1]<e){t.pop();n.pop()}t.push(i);n.push(e);return n[0]}var t=[],n=[],r=e;return i} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//rolling min max in probably fast javascript, if you treat javascript as c it is fast as c, i.e. no object arrays | |
// from http://stackoverflow.com/a/12195098/466363 | |
// https://gist.github.com/shimondoodkin/f274d6e17c66a8b72779 | |
function RollingMin(WindowSize)// generator | |
{ | |
var DequeIndex=[],DequeValue=[],CurrentIndex=0,T=WindowSize; | |
function atEveryStepDo(CurrentValue) | |
{ | |
if ( DequeIndex.length!==0 && DequeIndex[0] <= CurrentIndex - T ) | |
{ | |
DequeIndex.shift(); | |
DequeValue.shift(); | |
} | |
//Head is too old, it is leaving the window | |
while ( DequeValue.length!==0 && DequeValue[DequeValue.length-1] > CurrentValue ) | |
{ | |
DequeIndex.pop(); | |
DequeValue.pop(); | |
} | |
//remove elements that have no chance to become minimum in the window | |
DequeIndex.push(CurrentIndex); | |
DequeValue.push(CurrentValue); | |
CurrentIndex++; | |
return DequeValue[0] //Head value is minimum in the current window | |
} | |
return atEveryStepDo; | |
} | |
function RollingMax(WindowSize)// generator | |
{ | |
var DequeIndex=[],DequeValue=[],CurrentIndex=0,T=WindowSize; | |
function atEveryStepDo(CurrentValue) | |
{ | |
if ( DequeIndex.length!==0 && DequeIndex[0] <= CurrentIndex - T ) | |
{ | |
DequeIndex.shift(); | |
DequeValue.shift(); | |
} | |
//Head is too old, it is leaving the window | |
while ( DequeValue.length!==0 && DequeValue[DequeValue.length-1] < CurrentValue ) | |
{ | |
DequeIndex.pop(); | |
DequeValue.pop(); | |
} | |
//remove elements that have no chance to become maxbimum in the window | |
DequeIndex.push(CurrentIndex); | |
DequeValue.push(CurrentValue); | |
CurrentIndex++; | |
return DequeValue[0] //Head value is maximum in the current window | |
} | |
return atEveryStepDo; | |
} | |
function RollingMinIndex(WindowSize)// generator | |
{ | |
var DequeIndex=[],DequeValue=[],T=WindowSize; | |
function atEveryStepDo(CurrentValue,CurrentIndex) | |
{ | |
if ( DequeIndex.length!==0 && DequeIndex[0] <= CurrentIndex - T ) | |
{ | |
DequeIndex.shift(); | |
DequeValue.shift(); | |
} | |
//Head is too old, it is leaving the window | |
while ( DequeValue.length!==0 && DequeValue[DequeValue.length-1] > CurrentValue ) | |
{ | |
DequeIndex.pop(); | |
DequeValue.pop(); | |
} | |
//remove elements that have no chance to become minimum in the window | |
DequeIndex.push(CurrentIndex); | |
DequeValue.push(CurrentValue); | |
return DequeValue[0] //Head value is minimum in the current window | |
} | |
return atEveryStepDo; | |
} | |
function RollingMaxIndex(WindowSize)// generator | |
{ | |
var DequeIndex=[],DequeValue=[],T=WindowSize; | |
function atEveryStepDo(CurrentValue,CurrentIndex) | |
{ | |
if ( DequeIndex.length!==0 && DequeIndex[0] <= CurrentIndex - T ) | |
{ | |
DequeIndex.shift(); | |
DequeValue.shift(); | |
} | |
//Head is too old, it is leaving the window | |
while ( DequeValue.length!==0 && DequeValue[DequeValue.length-1] < CurrentValue ) | |
{ | |
DequeIndex.pop(); | |
DequeValue.pop(); | |
} | |
//remove elements that have no chance to become maxbimum in the window | |
DequeIndex.push(CurrentIndex); | |
DequeValue.push(CurrentValue); | |
return DequeValue[0] //Head value is maximum in the current window | |
} | |
return atEveryStepDo; | |
} | |
/* | |
example: | |
min=RollingMin(4);// use generator | |
> min(3) | |
3 | |
> min(3) | |
3 | |
> min(3) | |
3 | |
> min(2) | |
2 | |
> min(4) | |
2 | |
> min(4) | |
2 | |
> min(4) | |
2 | |
> min(4) | |
4 | |
> | |
max=RollingMax(4);// use generator | |
max(1) | |
1 | |
> max(1) | |
1 | |
> max(3) | |
3 | |
> max(2) | |
3 | |
> max(2) | |
3 | |
> max(2) | |
3 | |
> max(2) | |
2 | |
> | |
mint=RollingMinIndex(4000);// min values of last 4 seconds | |
> mint(3,new Date().getTime()+ 0); | |
3 | |
> mint(4,new Date().getTime()+1000); | |
3 | |
> mint(3,new Date().getTime()+2000); | |
3 | |
> mint(5,new Date().getTime()+5000); | |
3 | |
> mint(6,new Date().getTime()+10000); | |
5 | |
> mint(7,new Date().getTime()+20000); | |
6 | |
> mint(8,new Date().getTime()+30000); | |
7 | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//rolling min max in readable javascript | |
// from http://stackoverflow.com/a/12195098/466363 | |
Object.defineProperty(Array.prototype, 'Empty', { get: function() { return this.length==0}, enumerable: false, configurable: true }); | |
Object.defineProperty(Array.prototype, 'Head', { get: function() { return this[0]}, enumerable: false, configurable: true }); | |
Object.defineProperty(Array.prototype, 'Tail', { get: function() { return this[this.length-1]}, enumerable: false, configurable: true }); | |
Object.defineProperty(Array.prototype, 'AddTail', { value: function(Value, Index) { return this.push({Value:Value, Index:Index})}, enumerable: false, configurable: true }); | |
Object.defineProperty(Array.prototype, 'ExtractHead', { get: function() { return this.shift()}, enumerable: false, configurable: true }); | |
Object.defineProperty(Array.prototype, 'ExtractTail', { get: function() { return this.pop()}, enumerable: false, configurable: true }); | |
function RollingMin(WindowSize)// generator | |
{ | |
var Deque=[],CurrentIndex=0,T=WindowSize; | |
function atEveryStepDo(CurrentValue) | |
{ | |
if ( (!Deque.Empty) && (Deque.Head.Index <= CurrentIndex - T) ) | |
Deque.ExtractHead; | |
//Head is too old, it is leaving the window | |
while ( (!Deque.Empty) && (Deque.Tail.Value > CurrentValue) ) | |
Deque.ExtractTail; | |
//remove elements that have no chance to become minimum in the window | |
Deque.AddTail(CurrentValue, CurrentIndex); | |
var CurrentMin = Deque.Head.Value | |
//Head value is minimum in the current window | |
CurrentIndex++; | |
//atEveryStepDo.min=CurrentMin; | |
return CurrentMin; | |
} | |
return atEveryStepDo; | |
} | |
function RollingMax(WindowSize)// generator | |
{ | |
var Deque=[],CurrentIndex=0,T=WindowSize; | |
function atEveryStepDo(CurrentValue) | |
{ | |
if ( (!Deque.Empty) && (Deque.Head.Index <= CurrentIndex - T) ) | |
Deque.ExtractHead; | |
//Head is too old, it is leaving the window | |
while ( (!Deque.Empty) && (Deque.Tail.Value < CurrentValue) ) | |
Deque.ExtractTail; | |
//remove elements that have no chance to become maximum in the window | |
Deque.AddTail(CurrentValue, CurrentIndex); | |
var CurrentMax = Deque.Head.Value | |
//Head value is maximum in the current window | |
CurrentIndex++; | |
//atEveryStepDo.max=CurrentMax; | |
return CurrentMax; | |
} | |
return atEveryStepDo; | |
} | |
function RollingMinIndex(WindowSize)// generator, //Inedex is useful for time, than windwos size is miliseconds max offset | |
{ | |
var Deque=[],T=WindowSize; | |
function atEveryStepDo(CurrentValue,CurrentIndex) | |
{ | |
if ( (!Deque.Empty) && (Deque.Head.Index <= CurrentIndex - T) ) | |
Deque.ExtractHead; | |
//Head is too old, it is leaving the window | |
while ( (!Deque.Empty) && (Deque.Tail.Value > CurrentValue) ) | |
Deque.ExtractTail; | |
//remove elements that have no chance to become minimum in the window | |
Deque.AddTail(CurrentValue, CurrentIndex); | |
var CurrentMin = Deque.Head.Value | |
//Head value is minimum in the current window | |
//atEveryStepDo.min=CurrentMin; | |
return CurrentMin; | |
} | |
return atEveryStepDo; | |
} | |
function RollingMaxIndex(WindowSize)// generator | |
{ | |
var Deque=[],T=WindowSize; | |
function atEveryStepDo(CurrentValue,CurrentIndex) | |
{ | |
if ( (!Deque.Empty) && (Deque.Head.Index <= CurrentIndex - T) ) | |
Deque.ExtractHead; | |
//Head is too old, it is leaving the window | |
while ( (!Deque.Empty) && (Deque.Tail.Value < CurrentValue) ) | |
Deque.ExtractTail; | |
//remove elements that have no chance to become maximum in the window | |
Deque.AddTail(CurrentValue, CurrentIndex); | |
var CurrentMax = Deque.Head.Value | |
//Head value is maximum in the current window | |
//atEveryStepDo.max=CurrentMax; | |
return CurrentMax; | |
} | |
return atEveryStepDo; | |
} | |
/* | |
example: | |
min=RollingMin(4);// use generator | |
> min(3) | |
3 | |
> min(3) | |
3 | |
> min(3) | |
3 | |
> min(2) | |
2 | |
> min(4) | |
2 | |
> min(4) | |
2 | |
> min(4) | |
2 | |
> min(4) | |
4 | |
> | |
max=RollingMax(4);// use generator | |
max(1) | |
1 | |
> max(1) | |
1 | |
> max(3) | |
3 | |
> max(2) | |
3 | |
> max(2) | |
3 | |
> max(2) | |
3 | |
> max(2) | |
2 | |
> | |
mint=RollingMinIndex(4000);// min values of last 4 seconds | |
> mint(3,new Date().getTime()+ 0); | |
3 | |
> mint(4,new Date().getTime()+1000); | |
3 | |
> mint(3,new Date().getTime()+2000); | |
3 | |
> mint(5,new Date().getTime()+5000); | |
3 | |
> mint(6,new Date().getTime()+10000); | |
5 | |
> mint(7,new Date().getTime()+20000); | |
6 | |
> mint(8,new Date().getTime()+30000); | |
7 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment