Numeric Array prototypes

# Gbadebo Bello (6 years ago)

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

  1. Array.prorotype.min()
  2. Array.prorotype.max()
  3. Array.prorotype.mean()
  4. Array.prorotype.median()
  5. Array.prorotype.mode()
  6. Array.prototype.stdev()

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) }

# Isiah Meadows (6 years ago)

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.

# Michael Luder-Rosefield (6 years ago)

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.

# Isiah Meadows (6 years ago)

It doesn't work as well with larger collections.

Personally, it makes most sense in a standard library module

# T.J. Crowder (6 years ago)

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

# Isiah Meadows (6 years ago)

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.)

# Gbadebo Bello (6 years ago)

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

# Gbadebo Bello (6 years ago)

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?

# kai zhu (6 years ago)

@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.

# Jordan Harband (6 years ago)

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.

# kai zhu (6 years ago)

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.

# Isiah Meadows (6 years ago)

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

# MichaƂ Wadas (6 years ago)

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

# T.J. Crowder (6 years ago)

On Thu, Nov 22, 2018 at 3:48 AM kai zhu <kaizhu256 at gmail.com> wrote:

the spread operator was a mistake.

It's neither an operator nor a mistake.

Again, please stop wasting the list's time with re-litigating decisions that have been made.

-- T.J. Crowder