Numeric Array prototypes
Not sure these belong in the standard library itself. I could see max and
min being there (these are very broadly useful), but the others, not so
much. I'd also like both max and min accept an optional comparison callback
of (a, b) => a < b
. But the rest seem too narrowly useful IMHO.
Math.min() method doesn't work on Arrays right out of the box.
No, but rest parameters work: Math.min(...arr) is fine, and works with Sets too.
It doesn't work as well with larger collections.
Personally, it makes most sense in a standard library module
On Wed, Nov 21, 2018 at 7:23 AM Isiah Meadows <isiahmeadows at gmail.com> wrote:
It doesn't work as well with larger collections.
For example, fails at somewhere between an array of length 125,000 and
126,000 on V8 in Chrome v70 (as does the apply
trick, so the proposed
polyfill would have the same problem): jsfiddle.net/xoLe5mg7 Using
spread (it's not rest) also means that it would have to go through an
iterator, which if the iterable is known to be an array is a lot of extra
overhead (but also makes it more generally useful, so, swings and
roundabouts).
@Gbadebo Bello - What makes reduce
not suitable to your use cases?
Example:
function findMin(array) {
return array.reduce((a, b) => a < b ? a : b);
}
or if you want the type check:
function findMin(array) {
return array.reduce((a, b) => {
if (typeof a !== "number" || typeof b !== "number") {
throw new Error("The array must contain only numbers");
}
return a < b ? a : b;
});
}
(both off-the-cuff, apologies if there are any minor errors; the overall point should be clear regardless.)
If the callback becomes important from a performance perspective, I'd expect it to get aggressively optimized.
-- T.J. Crowder
An advantage to having this an internal primitive is you can use vector instructions to check 4-8 values in parallel and then end with a final step of finding the max/min value of the vector. (integers can just use bit hacks, float max/min has hardware acceleration).
The arithmetic mean could be similarly optimized via floating point vector instructions (divide by length, horizontal add), but the median and mode both would have to be done in serial IIRC and their algorithms are considerably more complex. (You also need more than O(1) space for both.) I could see the mean in a standard library module, but median and mode are so rarely useful in general, not even Lodash has them. (Really, not even Java has them.)
BTW, I take back the claim of low use case or need for mean. (It does have language and library precedent, and it's non-obvious to get right for iterators.)
Well, you are right. The apply
method might not be the best(Performance
wise).
@T.J. Crowder. Wow, my mind didn't go to reduce
at all, I don't have any
issues with it, in fact I feel it would perform better than apply
An advantage to having this an internal primitive is you can use vector
instructions to check 4-8 values in parallel and then end with a final step of finding the max/min value of the vector. (integers can just use bit hacks, float max/min has hardware acceleration).
I don't quite understand, does javascript now support vectorised operations on the client side or an external library would be needed for this?
@gbadebo, no he's talking about vectorized operations in c++ or whatever native-language the js-engine is implemented in.
the spread operator was a mistake. it's redundant to Object.p.apply (violates python/jslint maxim of one-way of doing things), the syntax increases cost of maintaining minifiers (for those who dislike webpack's monopoly, and prefer zero-config, zero-dependency alternatives like [classic] uglifyjs), and has performance footguns like the one mentioned by @tj.
Python and JSLint aren't in any way the arbiters of what's idiomatic in JS; webpack is not a minifier, it's a bundler; I believe uglify-es exists, but most people use babel and uglify, in my experience, which work fine.
Please don't derail this thread about numeric methods on array prototypes with complaints about the spread operator, thanks.
sorry for derailing, i just have many tooling/operational gripes on es6 (and reminding of past mistakes so they're not repeated is not necessarily bad thing).
but yea max, min, mean (and maybe sumOfSquares), are common-enough array-tasks they would be useful as optimized (maybe also numerically-stable) built-in methods.
No, I'm referring to how it'd be implemented. JS implementations might choose to leverage native vector CPU instructions in their code gen to speed them up by a factor of 1.5-3.
Isiah Meadows contact at isiahmeadows.com, www.isiahmeadows.com
On side note, it would be beneficial to have selection in standard library. This would cover median, min and max cases. stevehanov.ca/blog/index.php?id=122
The array object has no method for finding the minimum value of an array of numbers and the Math.min() method doesn't work on Arrays right out of the box. I'll have similar issues if i wanted to return the maximum number, the mean, mode, median or standard deviations in any array of numbers.
This is a bit tasky and can be done in just a line of code if there where Array.prototype.{method}() for it.
My proposal is, Arrays should have the following prototypes
The mean, median and mode would be very useful when visuali Here's is a polyfill of what i'll love to propose.
//Array.prototype.min() Array.prototype.min = function(){ let arrayVal = this; let checkNonNumbers = this.some(element => {
if(typeof(element) !== typeof(Math.random())){ throw new Error("This Array.prorotype.min() takes only array of numbers as arguments"); } else{ return true; } }); function findMin(validated){ if(validated == true){ return Math.min.apply( Math, arrayVal ); } } return findMin(checkNonNumbers); }
Similarly, Array.prototype.max() can be implemented as above.
//Array.prototype.median() Array.prototype.median = function(){ let values = this; function median(values){ values.sort(function(a,b){ return a-b; }); if(values.length ===0) return 0 var half = Math.floor(values.length / 2); if (values.length % 2) return values[half]; else return (values[half - 1] + values[half]) / 2.0; } return median(numbers) }