Skip to content

Instantly share code, notes, and snippets.

@imvenj
Created April 17, 2019 08:27
Show Gist options
  • Save imvenj/0700741bdf6f5decdbd57365e1caf806 to your computer and use it in GitHub Desktop.
Save imvenj/0700741bdf6f5decdbd57365e1caf806 to your computer and use it in GitHub Desktop.
SMA implementation in simple function form, or in class form.
// Simple move average
function sma(data, dataLength, sampleRate=250, frequency=50) {
if (data.length === 0) return data;
const filterTL = Math.round(sampleRate / frequency)
const filteredData = []
if (filterTL > dataLength) {
throw new Error('Data length is not enough.')
}
else {
for (let i = 0; i < dataLength; ++i) {
if (i <= dataLength - filterTL) {
let sum = 0
for (let j = i; j < i + filterTL; ++j) {
sum += data[j]
}
const average = sum / filterTL
filteredData.push(average)
}
else {
filteredData.push(0) // Not necessary, maybe.
}
}
return filteredData
}
}
class SMACalculator {
constructor(sampleRate = 250, frequency = 50) {
this.container = []
this.sampleRate = sampleRate
this.frequency = frequency
this.batchSize = Math.round(sampleRate / frequency)
this.lastValue = null
this.sum = null
}
update(newData = []) {
console.log(`this.container length: ${this.container.length}`, this.container)
const tempArray = this.container.concat(newData)
const dataLength = tempArray.length
const maxMoveIndex = dataLength - this.batchSize
console.log(`maxMoveIndex: ${maxMoveIndex}`)
// 如果传入的数组成员数不足,则存入容器,返回空数组
if (dataLength < this.batchSize) {
this.container = tempArray
return []
}
// 开始移动。
const result = []
this.container = [] // 清空缓存
for (let i = 0; i < dataLength; ++i) {
// 计算移动平均值
if (i <= maxMoveIndex) {
// 计算 sum。
if (this.sum === null) { // 第一次进入,先算出 sum 的初始值
for (let j = 0; j < this.batchSize; ++j) {
this.sum += tempArray[j]
}
}
else {
// 非第一轮运算时,当 i 为 0 时,调用缓存的 lastValue,否则直接用前一个值。
const lastValue = (i === 0) ? this.lastValue : tempArray[i-1]
console.log(`lastValue: ${lastValue}`)
this.sum = this.sum - lastValue + tempArray[i + this.batchSize - 1]
}
const average = this.sum / this.batchSize
result.push(average) // 推入平均值
// 存下参与计算的最后一个值
if (i === maxMoveIndex) {
this.lastValue = tempArray[i]
}
}
else {
this.container.push(tempArray[i]) //缓存未参与运算的值
}
}
return result
}
reset() {
this.container = []
this.lastValue = null
this.sum = null
}
}
const orig = [97,72,98,83,71,99,90,28,98,58,49,4,98,78,1,63,85,92,56,96,17,59,38,34,21,97,76,86,87,99,98,2,11,96,91,14,19,19,38]
const orig1 = [97,72,98,83,71,99,90,28]
const orig2 = [98,58,49,4,98,78,1,63,85,92,56,96]
const orig3 = [17,59,38,34,21,97,76,86,87,99,98,2,11,96,91]
const orig4 = [14,19,19,38]
const calc = new SMACalculator()
const result = calc.update(orig)
const calc2 = new SMACalculator()
const result2 = calc2.update(orig1).concat(calc2.update(orig2)).concat(calc2.update(orig3)).concat(calc2.update(orig4))
console.log(`orig: ${orig.length}`)
console.log(`Class: ${result}`, `${result.length}`)
console.log(`Class: ${result2}`, `${result2.length}`)
console.log(`Function: ${sma(orig, orig.length)}`, `${sma(orig, orig.length).length}`)
// const calc = new SMACalculator()
// let result = calc.update(orig1)
// console.log(`result: ${result.length}`, result)
// result = calc.update(orig2)
// console.log(`result: ${result.length}`, result)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment