Walter Bright:
> This C++0x article is relevant for comparison:
> http://www.reddit.com/r/programming/comments/8bijk/gcc_c0x_features_exploration/
"Advanced" features have to be used only if they improve the code. I don't like
that little article and the following discussion.
The following D1 code shows two ways to solve that problem with my dlibs. The
first code to try is the simplest, that is to scan the data three (or even four
times):
double avg = cast(double)sum(data) / len(data);
putr("min, max, avg: ", min(data), " ", max(data), " ", avg);
It works with most kind of eager/lazy numerical data, for example a lazy
generator that has no length. Note that sum() is sometimes faster than a simple
loop.
In many situations that code (plus some safety against division by zero) is
good enough.
If you know data is huge or you have found that code to be a bottleneck, and
you want a single pass you can use something like the following (code written
on the fly, no unittests present, it may contain bugs):
import d.templates: IsAA, BaseType1, Record;
import d.func: putr, min, max, sum, record, len;
import d.exceptions: EmptyException;
Record!(BaseType1!(TSeq), BaseType1!(TSeq), double) minMaxAvg1(TSeq)(TSeq seq,
double start=0.0) {
auto nitems = len(seq);
if (!nitems)
throw new EmptyException("minMaxAvg(): 'seq' can't be empty");
return record(min(seq), max(seq), sum(seq, start) / nitems);
}
Record!(BaseType1!(TSeq), BaseType1!(TSeq), double) minMaxAvg2(TSeq)(TSeq seq,
double start=0.0) {
BaseType1!(TSeq) dmin, dmax;
double dtot = start;
int nitems;
static if (IsAA!(TSeq)) {
foreach (el, _; seq) {
if (nitems == 0) {
dmin = el;
dmax = el;
}
if (dmin > el) dmin = el;
if (dmax < el) dmax = el;
dtot += el;
nitems++;
}
} else {
foreach (el; seq) {
if (nitems == 0) {
dmin = el;
dmax = el;
}
if (dmin > el) dmin = el;
if (dmax < el) dmax = el;
dtot += el;
nitems++;
}
}
if (!nitems)
throw new EmptyException("minMaxAvg(): 'seq' can't be empty");
return record(dmin, dmax, dtot / nitems);
}
void main() {
int[] data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
putr("<min, max, avg>: ", minMaxAvg1(data));
putr("<min, max, avg>: ", minMaxAvg2(data));
}
(Notice the ugly code duplication caused by the AAs).
The output:
min, max, avg: 1 10 5.5
<min, max, avg>: record(1, 10, 5.5)
Bye,
bearophile