/* http://www.nist.gov/dads/HTML/mean.html */
var mean = function() {
var data = flattenArguments(arguments);
return sum(data) / data.length;
};
/* http://www.nist.gov/dads/HTML/median.html */
var median = function() {
var data = flattenArguments(arguments);
data.sort(compare);
if (data.length % 2 == 0) {
var upper = data.length / 2;
return (data[upper] + data[upper - 1]) / 2;
} else {
return data[(data.length - 1) / 2];
}
};
>>> mean(1, [2, [3]]) === 2
true
>>> mean(1, 2, 3) === 2
true
>>> median(3, 1, 2) === 2
true
>>> median(4,2,3,1) === 2.5
true
On Wed, 21 Jun 2006 16:32:13 -0700, Beau Hartshorne <harts...@gmail.com>
> >>> mean(1, [2, [3]]) === 2
>true
that's a bit weird. maybe mean/median should expect a single, flat list argument? wanting to know the mean of a bunch of nested lists is such a bizarre request that i don't think it's unreasonable to require that the caller flattens the arguments.
>
> I needed median and mean functions for something I'm working on.
> Should they go into MochiKit somewhere? Are they correct? Fast enough?
>
> /* http://www.nist.gov/dads/HTML/mean.html */
> var mean = function() {
> var data = flattenArguments(arguments);
> return sum(data) / data.length;
> };
>
> /* http://www.nist.gov/dads/HTML/median.html */
> var median = function() {
> var data = flattenArguments(arguments);
> data.sort(compare);
> if (data.length % 2 == 0) {
> var upper = data.length / 2;
> return (data[upper] + data[upper - 1]) / 2;
> } else {
> return data[(data.length - 1) / 2];
> }
> };
These look correct and fast enough. I might've written mean such that
it inlined more or less what flattenArguments does and calculated the
sum and length at the same time without building an intermediate
Array at all. median could be similarly special cased but that would
be a pain in the ass to do faster and it isn't really very commonly
used anyway. Note that using sum() currently introduces a dependency
on MochiKit.Iter, but I'd be open to moving it to MochiKit.Base and
specialize based upon the input type and iter availability like map()
does.
The empty list cases should be handled somehow.. mean obviously
returns NaN because it's doing divide by zero, but median much less
obviously returns NaN: (undefined + undefined)/2. I'm not sure if
people would expect 0.0 or an error to be thrown, I doubt NaN is
desired though.
Renaming mean to average or avg might make sense. I think more people
are familiar with the term average.
-bob
That's basically a side-effect of allowing both mean([1,2,3]) and mean
(1,2,3) via flattenArguments.
-bob
i'm not so sure that the two character win of mean(1, 2, 3) over mean([1, 2, 3]) is worth it. debugging javascript is troublesome as it is, and returning a result for ambiguous/nonsense inputs like 1, [2, [3]] can't help, especially when it's inconsistent with the behaviour of similar functions in the same library - e.g. MochiKit.Iter.sum(1, [2, [3]]) -> ValueError: "1 is not iterable" (and confusingly, MochiKit.Iter.sum([1, [2, [3]]]) -> "12,3" in MK 1.4)
It's pretty much consistent with what Python does:
>>> min(1,2,3)
1
>>> min([1,2,3])
1
>>> sum(1,2,3)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: sum expected at most 2 arguments, got 3
>>> sum([1,2,3])
6
I don't think the collapsing of nested array is a big deal. I
wouldn't document it as a feature, it's just an implementation detail.
The fact that adding a number and an array gives you a nonsense
string is just something you have to live with in JavaScript.
-bob
I'll work on mean. Moving sum seems like way more work than just
writing a loop. Instead of renaming mean, what about aliasing it (and
note that in the docs)? Here's what JavaScript does with similar
functions that expect arguments:
>>> Math.min()
Infinity
>>> Math.max()
-Infinity
>>> Math.ceil()
NaN
>>> Math.cos()
NaN
And MochiKit:
>>> listMin()
TypeError: Undefined value [...]
>>> listMax()
TypeError: Undefined value [...]
>>> listMin([])
null
>>> listMax([])
null
I think listMin and listMax follow Math.min and .max. mean and median
should probably return NaN.