Is there a better way to calculate a moving sum of a list?
List<double?> rollingSum({int window = 3, List data = const []}) {
List<double?> sum = [];
int i = 0;
int maxLength = data.length - window 1;
while (i < maxLength) {
List tmpData = data.getRange(i, i window).toList();
double tmpSum = tmpData.reduce((a, b) => a b);
sum.add(tmpSum);
i ;
}
// filling the first n values with null
i = 0;
while (i < window - 1) {
sum.insert(0, null);
i ;
}
return sum;
}
CodePudding user response:
Well, the code is already clean for what you need. Maybe just some improvements like:
- Use a
for loop
- You can use the method
sublist
which creates a "view" of a list, which is more efficient - To insert some values in the left/right of a list, there is a specific Dart method called
padLeft
, where you specify the lenght of the list which you want it to become (first parameter), then the value you want to use to fill it (second parameter). For example, if you have an array of N elements, and you want to fill it with X "null"s to the left, usepadLeft(N X, null)
.
List<double?> rollingSum({int window = 3, List data = const []}) {
List<double?> sum = [];
for (int i = 0; i < data.length - window 1; i ) {
List tmpData = data.sublist(i, i window);
double tmpSum = tmpData.reduce((a, b) => a b);
sum.add(tmpSum);
}
sum.padLeft(window - 1, null);
return sum;
}
CodePudding user response:
if I understand your problem correctly you can just calculate the window one time and in one loop you can for each iteration you can add the current element to the sum and subtract i - (window - 1)
so for an input like this
data
= [1,2,3,4,5,6]
window
= 3
the below code will result in [6,9,12,15]
int sum = 0;
List<double> res = [];
for (int i = 0;i<data.length;i ) {
sum = data[i];
if (i < window - 1) {
continue;
}
res.add(sum);
sum -= data[i - (window - 1)]; // remove element that got out of the window size
}
this way you won't have to use getRange
nor sublist
nor reduce
as all of those are expensive functions in terms of time and space complexity