Zoek het min/max-element van een array in JavaScript

Hoe kan ik eenvoudig het min of max element van een JavaScript-array verkrijgen?

Voorbeeld pseudocode:

let array = [100, 0, 50]
array.min() //=> 0
array.max() //=> 100

Antwoord 1, autoriteit 100%

Hoe zit het met het vergroten van het ingebouwde Array-object om Math.max/Math.min in plaats daarvan:

Array.prototype.max = function() {
  return Math.max.apply(null, this);
};
Array.prototype.min = function() {
  return Math.min.apply(null, this);
};

Hier is een JSFiddle.

Het vergroten van de ingebouwde functies kan leiden tot botsingen met andere bibliotheken (sommigen zien), dus het kan zijn dat u zich meer op uw gemak voelt door gewoon apply‘ing Math.xxx() op direct uw array:

var min = Math.min.apply(null, arr),
    max = Math.max.apply(null, arr);

Als alternatief, ervan uitgaande dat uw browser ECMAScript 6 ondersteunt, kunt u de spread-operator die op dezelfde manier werkt als de methode apply:

var min = Math.min( ...arr ),
    max = Math.max( ...arr );

Antwoord 2, autoriteit 43%

var max_of_array = Math.max.apply(Math, array);

Voor een volledige discussie zie:
http://aaroncrane.co.uk/2008/11/javascript_max_api/


Antwoord 3, autoriteit 26%

Voor grote arrays (~10? elementen) produceren Math.min en Math.max beide de volgende fout in Node.js.

RangeError: maximale call-stackgrootte overschreden

Een robuustere oplossing is om niet elk element aan de call-stack toe te voegen, maar in plaats daarvan een array door te geven:

function arrayMin(arr) {
  return arr.reduce(function (p, v) {
    return ( p < v ? p : v );
  });
}
function arrayMax(arr) {
  return arr.reduce(function (p, v) {
    return ( p > v ? p : v );
  });
}

Als je je zorgen maakt over snelheid, de volgende code is ~3 keer sneller dan Math.max.apply op mijn computer. Zie http://jsperf.com/min-and-max-in-array/2 .

function arrayMin(arr) {
  var len = arr.length, min = Infinity;
  while (len--) {
    if (arr[len] < min) {
      min = arr[len];
    }
  }
  return min;
};
function arrayMax(arr) {
  var len = arr.length, max = -Infinity;
  while (len--) {
    if (arr[len] > max) {
      max = arr[len];
    }
  }
  return max;
};

Als je arrays strings bevatten in plaats van getallen, moet je ze ook in getallen dwingen. De onderstaande code doet dat, maar het vertraagt ​​de code ~ 10 keer op mijn machine. Zie http://jsperf.com/min-and-max-in-array/3 .

function arrayMin(arr) {
  var len = arr.length, min = Infinity;
  while (len--) {
    if (Number(arr[len]) < min) {
      min = Number(arr[len]);
    }
  }
  return min;
};
function arrayMax(arr) {
  var len = arr.length, max = -Infinity;
  while (len--) {
    if (Number(arr[len]) > max) {
      max = Number(arr[len]);
    }
  }
  return max;
};

Antwoord 4, autoriteit 23%

Spread-operator (ES6) gebruiken

Math.max(...array);  // the same with "min" => Math.min(...array);

Antwoord 5, autoriteit 15%

tl;dr

// For regular arrays:
var max = Math.max(...arrayOfNumbers);
// For arrays with tens of thousands of items:
let max = testArray[0];
for (let i = 1; i < testArrayLength; ++i) {
  if (testArray[i] > max) {
    max = testArray[i];
  }
}

MDN-oplossing

De officiële MDN-documenten op Math.max() behandelt dit probleem al:

De volgende functie gebruikt Function.prototype. apply() om het maximum element in een numerieke array te vinden. getMaxOfArray([1, 2, 3]) is gelijk aan Math.max(1, 2, 3), maar je kunt getMaxOfArray() op programmatisch geconstrueerde arrays van elke grootte.

function getMaxOfArray(numArray) {
    return Math.max.apply(null, numArray);
}

Of met de nieuwe spread-operator , wordt het een stuk eenvoudiger om het maximum uit een array te halen.

var arr = [1, 2, 3];
var max = Math.max(...arr);

Maximale grootte van een array

Volgens MDN de apply en spread-oplossingen hadden een limiet van 65536 die voortkwam uit de limiet van het maximale aantal argumenten:

Maar let op: als u op deze manier van toepassing bent, loopt u het risico dat u de limiet van de argumentlengte van de JavaScript-engine overschrijdt. De gevolgen van het toepassen van een functie met te veel argumenten (denk aan meer dan tienduizenden argumenten) variëren per engine (JavaScriptCore heeft een hardgecodeerde argumentlimiet van 65536), omdat de limiet (inderdaad zelfs de aard van buitensporig groot stapelgedrag) is niet gespecificeerd. Sommige motoren zullen een uitzondering maken. Meer schadelijk, anderen zullen willekeurig het aantal argumenten beperken dat daadwerkelijk aan de toegepaste functie wordt doorgegeven. Om dit laatste geval te illustreren: als zo’n engine een limiet van vier argumenten had (de werkelijke limieten zijn natuurlijk aanzienlijk hoger), zou het zijn alsof de argumenten 5, 6, 2, 3 waren doorgegeven om van toepassing te zijn in de bovenstaande voorbeelden, in plaats van de volledige array.

Ze bieden zelfs een hybride oplossing die niet echt goede prestaties levert in vergelijking met andere oplossingen. Zie de prestatietest hieronder voor meer informatie.

In 2019 is de werkelijke limiet de maximale grootte van de call-stack. Voor moderne op Chromium gebaseerde desktopbrowsers betekent dit dat als het gaat om het vinden van min/max met apply of spread, praktisch de maximale grootte voor arrays met alleen getallen ~120000 is. Hierboven zal er een stack overflow zijn en wordt de volgende fout gegenereerd:

RangeError: maximale call-stackgrootte overschreden

Met het onderstaande script (gebaseerd op deze blogpost), door die fout op te vangen, kunt u de limiet voor uw specifieke omgeving berekenen.

Waarschuwing! Het uitvoeren van dit script kost tijd en afhankelijk van de prestaties van uw systeem kan het uw browser/systeem vertragen of laten crashen!

let testArray = Array.from({length: 10000}, () => Math.floor(Math.random() * 2000000));
for (i = 10000; i < 1000000; ++i) {
  testArray.push(Math.floor(Math.random() * 2000000));
  try {
    Math.max.apply(null, testArray);
  } catch (e) {
    console.log(i);
    break;
  }
}

Antwoord 6, autoriteit 7%

Als je net als ik paranoïde bent over het gebruik van Math.max.apply (wat fouten kan veroorzaken bij grote arrays volgens MDN), probeer dit:

function arrayMax(array) {
  return array.reduce(function(a, b) {
    return Math.max(a, b);
  });
}
function arrayMin(array) {
  return array.reduce(function(a, b) {
    return Math.min(a, b);
  });
}

Of, in ES6:

function arrayMax(array) {
  return array.reduce((a, b) => Math.max(a, b));
}
function arrayMin(array) {
  return array.reduce((a, b) => Math.min(a, b));
}

De anonieme functies zijn helaas noodzakelijk (in plaats van Math.max.bind(Math) te gebruiken omdat reduce niet zomaar a doorgeeft en b naar zijn functie, maar ook i en een verwijzing naar de array zelf, dus we moeten ervoor zorgen dat we niet proberen max ook daarop.


Antwoord 7, autoriteit 5%

Alternatieve methoden


De Math.min en Math.max zijn geweldige methoden om het minimale en maximale item uit een verzameling items te halen, maar het is belangrijk om op de hoogte te zijn van enkele gaatjes die daarbij horen.

Als u ze gebruikt met een array die een groot aantal items bevat (meer dan ~10? items, hangt af van de browser van de gebruiker), zal hoogstwaarschijnlijk crasht en de volgende foutmelding verschijnen:

const arr = Array.from(Array(1000000).keys());
Math.min(arr);
Math.max(arr);

Uncaught RangeError: maximale call-stack-grootte overschreden

UPDATE
De nieuwste browsers kunnen in plaats daarvan NaN retourneren. Dat is misschien een betere manier om met fouten om te gaan, maar het lost het probleem nog niet op.

Overweeg in plaats daarvan iets als dit te gebruiken:

function maxValue(arr) {
  return arr.reduce((max, val) => max > val ? max : val)
}

Of met een betere looptijd:

function maxValue(arr) {
  let max = arr[0];
  for (let val of arr) {
    if (val > max) {
      max = val;
    }
  }
  return max;
}

Of om zowel Min als Max te krijgen:

function getMinMax(arr) {
  return arr.reduce(({min, max}, v) => ({
    min: min < v ? min : v,
    max: max > v ? max : v,
  }), { min: arr[0], max: arr[0] });
}

Of met een nog betere runtime*:

function getMinMax(arr) {
  let min = arr[0];
  let max = arr[0];
  let i = arr.length;
  while (i--) {
    min = arr[i] < min ? arr[i] : min;
    max = arr[i] > max ? arr[i] : max;
  }
  return { min, max };
}

* Getest met 1.000.000 items:
Ter referentie: de runtime van de eerste functie (op mijn computer) was 15,84 ms versus de tweede functie met slechts 4,32 ms.


Antwoord 8, autoriteit 4%

.apply wordt vaak gebruikt wanneer het de bedoeling is om een ​​variadische functie aan te roepen met een lijst met argumentwaarden, bijv.

De Math.max([value1[,value2, ...]]) functie retourneert de grootste van nul of meer getallen.

Math.max(10, 20); // 20
Math.max(-10, -20); // -10
Math.max(-10, 20); // 20

De Math.max() methode staat je niet toe om een ​​array door te geven. Als je een lijst met waarden hebt waarvan je de grootste moet krijgen, zou je deze functie normaal gesproken aanroepen met Function.prototype.apply(), bijv.

Math.max.apply(null, [10, 20]); // 20
Math.max.apply(null, [-10, -20]); // -10
Math.max.apply(null, [-10, 20]); // 20

Vanaf de ECMAScript 6 kunt u echter de spread-operator:

Met de spread-operator kan een uitdrukking worden uitgebreid op plaatsen waar meerdere argumenten (voor functieaanroepen) of meerdere elementen (voor letterlijke arrays) worden verwacht.

Met behulp van de spread-operator kan het bovenstaande als zodanig worden herschreven:

Math.max(...[10, 20]); // 20
Math.max(...[-10, -20]); // -10
Math.max(...[-10, 20]); // 20

Als je een functie aanroept met de variadische operator, kun je zelfs extra waarden toevoegen, bijvoorbeeld

Math.max(...[10, 20], 50); // 50
Math.max(...[-10, -20], 50); // 50

Bonus:

Met de operator Spread kunt u de letterlijke syntaxis van arrays gebruiken om nieuwe arrays te maken in situaties waarin u in ES5 zou moeten terugvallen op imperatieve code, met behulp van een combinatie van push, splice, enz.

let foo = ['b', 'c'];
let bar = ['a', ...foo, 'd', 'e']; // ['a', 'b', 'c', 'd', 'e']

Antwoord 9, autoriteit 4%

Twee manieren zijn korter en gemakkelijk:

let arr = [2, 6, 1, 0]

Manier 1:

let max = Math.max.apply(null, arr)

Manier 2:

let max = arr.reduce(function(a, b) {
    return Math.max(a, b);
});

Antwoord 10, autoriteit 2%

Je doet het door het array-type uit te breiden:

Array.max = function( array ){
    return Math.max.apply( Math, array );
};
Array.min = function( array ){
    return Math.min.apply( Math, array );
}; 

Boosted van hier (door John Resig)


Antwoord 11, autoriteit 2%

Een eenvoudige oplossing om de minimumwaarde over een Array van elementen te vinden, is door de Array prototypefunctie reduce te gebruiken:

A = [4,3,-9,-2,2,1];
A.reduce((min, val) => val < min ? val : min, A[0]); // returns -9

of met behulp van de ingebouwde Math.Min()-functie van JavaScript (bedankt @Tenflex):

A.reduce((min,val) => Math.min(min,val), A[0]);

Dit stelt min in op A[0] en controleert vervolgens op A[1]...A[n] of het is strikt minder dan de huidige min. Als A[i] < min en vervolgens wordt min geüpdatet naar A[i]. Als alle array-elementen zijn verwerkt, wordt min als resultaat geretourneerd.

EDIT: positie van minimumwaarde opnemen:

A = [4,3,-9,-2,2,1];
A.reduce((min, val) => val < min._min ? {_min: val, _idx: min._curr, _curr: min._curr + 1} : {_min: min._min, _idx: min._idx, _curr: min._curr + 1}, {_min: A[0], _idx: 0, _curr: 0}); // returns { _min: -9, _idx: 2, _curr: 6 }

Antwoord 12, autoriteit 2%

Anderen hebben al enkele oplossingen gegeven waarin ze Array.prototype aanvullen. Het enige dat ik in dit antwoord wil, is verduidelijken of het Math.min.apply( Math, array ) of Math.min.apply( null, array ) moet zijn. Dus welke context moet worden gebruikt, Math of null?

Bij het doorgeven van null als context voor apply, dan zal de context standaard het globale object zijn (het window object in het geval van browsers). Het doorgeven van het object Math als context zou de juiste oplossing zijn, maar het kan ook geen kwaad om null door te geven. Hier is een voorbeeld wanneer null problemen kan veroorzaken bij het verfraaien van de functie Math.max:

// decorate Math.max
(function (oldMax) {
    Math.max = function () {
        this.foo(); // call Math.foo, or at least that's what we want
        return oldMax.apply(this, arguments);
    };
})(Math.max);
Math.foo = function () {
    print("foo");
};
Array.prototype.max = function() {
  return Math.max.apply(null, this); // <-- passing null as the context
};
var max = [1, 2, 3].max();
print(max);

Het bovenstaande veroorzaakt een uitzondering omdat this.foo wordt geëvalueerd als window.foo, wat undefined is. Als we null vervangen door Math, werken de dingen zoals verwacht en wordt de tekenreeks “foo” op het scherm afgedrukt (ik heb dit getest met Mozilla Rhino).

Je kunt er vrijwel van uitgaan dat niemand Math.max heeft versierd, dus het doorgeven van null zal zonder problemen werken.


Antwoord 13, autoriteit 2%

Nog een manier om het te doen:

var arrayMax = Function.prototype.apply.bind(Math.max, null);

Gebruik:

var max = arrayMax([2, 5, 1]);

Antwoord 14, autoriteit 2%

Het verbaast me dat niemand de reduceerfunctie noemde.

var arr = [1, 10, 5, 11, 2]
var b = arr.reduce(function(previous,current){ 
                      return previous > current ? previous:current
                   });
b => 11
arr => [1, 10, 5, 11, 2]

Antwoord 15

https://developer.mozilla.org/ ru/docs/Web/JavaScript/Reference/Global_Objects/Math/max

function getMaxOfArray(numArray) {
  return Math.max.apply(null, numArray);
}
var arr = [100, 0, 50];
console.log(getMaxOfArray(arr))

Antwoord 16

Dit kan geschikt zijn voor uw doeleinden.

Array.prototype.min = function(comparer) {
    if (this.length === 0) return null;
    if (this.length === 1) return this[0];
    comparer = (comparer || Math.min);
    var v = this[0];
    for (var i = 1; i < this.length; i++) {
        v = comparer(this[i], v);    
    }
    return v;
}
Array.prototype.max = function(comparer) {
    if (this.length === 0) return null;
    if (this.length === 1) return this[0];
    comparer = (comparer || Math.max);
    var v = this[0];
    for (var i = 1; i < this.length; i++) {
        v = comparer(this[i], v);    
    }
    return v;
}

Antwoord 17

Voor een beknopte, moderne oplossing kan men een reduce bewerking over de array, waarbij de huidige minimum- en maximumwaarden worden bijgehouden, zodat de array maar één keer wordt herhaald (wat optimaal is). Destructuring-toewijzing wordt hier gebruikt voor de beknoptheid.

let array = [100, 0, 50];
let [min, max] = array.reduce(([prevMin,prevMax], curr)=>
   [Math.min(prevMin, curr), Math.max(prevMax, curr)], [Infinity, -Infinity]);
console.log("Min:", min);
console.log("Max:", max);

Antwoord 18

Voor grote arrays (~10? elementen), produceren Math.min en Math.max een RangeError (maximale call-stackgrootte overschreden) in node.js.

Voor grote arrays, een snelle & vuile oplossing is:

Array.prototype.min = function() {
    var r = this[0];
    this.forEach(function(v,i,a){if (v<r) r=v;});
    return r;
};

Antwoord 19

let array = [267, 306, 108]
let langst = Math.max(…array);


Antwoord 20

Ik had hetzelfde probleem, ik moest de minimum- en maximumwaarden van een array verkrijgen en tot mijn verbazing waren er geen ingebouwde functies voor arrays. Na veel gelezen te hebben, besloot ik de “top 3” oplossingen zelf te testen:

  1. discrete oplossing: een FOR-lus om elk element van de array te vergelijken met de huidige max- en/of min-waarde;
  2. APPLY-oplossing: de array verzenden naar de interne functies Math.max en/of Math.min met behulp van apply(null,array);
  3. REDUCE-oplossing: een controle herhalen voor elk element van de array met behulp van reduce(function).

De testcode was deze:

function GetMaxDISCRETE(A)
{   var MaxX=A[0];
    for (var X=0;X<A.length;X++)
        if (MaxX<A[X])
            MaxX=A[X];
    return MaxX;
}
function GetMaxAPPLY(A)
{   return Math.max.apply(null,A);
}
function GetMaxREDUCE(A)
{   return A.reduce(function(p,c)
    {   return p>c?p:c;
    });
}

De array A was gevuld met 100.000 willekeurige gehele getallen, elke functie werd 10.000 keer uitgevoerd in Mozilla Firefox 28.0 op een Intel Pentium 4 2.99GHz-desktop met Windows Vista. De tijden zijn in seconden, opgehaald door de functie performance.now(). De resultaten waren deze, met 3 fractionele cijfers en standaarddeviatie:

  1. Discrete oplossing: mean=0.161s, sd=0.078
  2. OPLOSSING TOEPASSEN: mean=3.571s, sd=0.487
  3. VERMINDER oplossing: gemiddelde=0.350s, sd=0.044

De REDUCE-oplossing was 117% langzamer dan de discrete oplossing. De APPLY-oplossing was de slechtste, 2,118% langzamer dan de discrete oplossing. Trouwens, zoals Peter opmerkte, werkt het niet voor grote arrays (ongeveer meer dan 1.000.000 elementen).

Ook om de tests te voltooien, heb ik deze uitgebreide discrete code getest:

var MaxX=A[0],MinX=A[0];
for (var X=0;X<A.length;X++)
{   if (MaxX<A[X])
        MaxX=A[X];
    if (MinX>A[X])
        MinX=A[X];
}

De timing: gemiddelde=0.218s, sd=0.094

Het is dus 35% langzamer dan de eenvoudige discrete oplossing, maar het haalt zowel de maximum- als de minimumwaarden tegelijk op (elke andere oplossing zou er minstens twee keer zoveel voor nodig hebben om ze op te halen). Zodra de OP beide waarden nodig had, zou de discrete oplossing de beste keuze zijn (zelfs als twee afzonderlijke functies, een voor het berekenen van het maximum en een ander voor het berekenen van het minimum, zouden ze beter presteren dan de op één na beste, de REDUCE-oplossing).


Antwoord 21

U kunt de volgende functie overal in uw project gebruiken:

function getMin(array){
    return Math.min.apply(Math,array);
}
function getMax(array){
    return Math.max.apply(Math,array);
}

En dan kun je de functies aanroepen die de array doorgeven:

var myArray = [1,2,3,4,5,6,7];
var maximo = getMax(myArray); //return the highest number

Antwoord 22

Ik dacht dat ik mijn eenvoudige en gemakkelijk te begrijpen oplossing zou delen.

Voor de min:

var arr = [3, 4, 12, 1, 0, 5];
var min = arr[0];
for (var k = 1; k < arr.length; k++) {
  if (arr[k] < min) {
    min = arr[k];
  }
}
console.log("Min is: " + min);

Antwoord 23

De volgende code werkt voor mij:

var valueList = [10,4,17,9,3];
var maxValue = valueList.reduce(function(a, b) { return Math.max(a, b); });
var minValue = valueList.reduce(function(a, b) { return Math.min(a, b); });

Antwoord 24

Naast het gebruik van de wiskundige functie max en min, is een andere functie om te gebruiken de ingebouwde functie van sort(): hier gaan we

const nums = [12, 67, 58, 30].sort((x, y) => 
x -  y)
let min_val = nums[0]
let max_val = nums[nums.length -1]

Antwoord 25

Herhaal door, houd bij terwijl je bezig bent.

var min = null;
var max = null;
for (var i = 0, len = arr.length; i < len; ++i)
{
    var elem = arr[i];
    if (min === null || min > elem) min = elem;
    if (max === null || max < elem) max = elem;
}
alert( "min = " + min + ", max = " + max );

Dit laat min/max null achter als er geen elementen in de array staan. Stelt min en max in één keer in als de array elementen bevat.

Je zou Array ook kunnen uitbreiden met een range methode met behulp van de bovenstaande methode om hergebruik mogelijk te maken en de leesbaarheid te verbeteren. Bekijk een werkende viool op http://jsfiddle.net/9C9fU/

Array.prototype.range = function() {
    var min = null,
        max = null,
        i, len;
    for (i = 0, len = this.length; i < len; ++i)
    {
        var elem = this[i];
        if (min === null || min > elem) min = elem;
        if (max === null || max < elem) max = elem;
    }
    return { min: min, max: max }
};

Gebruikt als

var arr = [3, 9, 22, -7, 44, 18, 7, 9, 15];
var range = arr.range();
console.log(range.min);
console.log(range.max);

Antwoord 26

let arr=[20,8,29,76,7,21,9]
Math.max.apply( Math, arr ); // 76


Antwoord 27

Eenvoudig, eigenlijk.

var arr = [10,20,30,40];
arr.max = function() { return  Math.max.apply(Math, this); }; //attach max funct
arr.min = function() { return  Math.min.apply(Math, this); }; //attach min funct
alert("min: " + arr.min() + " max: " + arr.max());

Antwoord 28

Hier is een manier om de maximale waarde uit een reeks objecten te halen. Maak een kopie (met plak), sorteer de kopie vervolgens in aflopende volgorde en pak het eerste item.

var myArray = [
    {"ID": 1, "Cost": 200},
    {"ID": 2, "Cost": 1000},
    {"ID": 3, "Cost": 50},
    {"ID": 4, "Cost": 500}
]
maxsort = myArray.slice(0).sort(function(a, b) { return b.ID - a.ID })[0].ID; 

Antwoord 29

Math.max() of Math.min()

gebruiken

Math.max(10, 20);   //  20
Math.min(-10, -20); // -20

De volgende functie gebruikt Function.prototype.apply() om het maximumelement in een numerieke array te vinden. getMaxOfArray([1, 2, 3]) is gelijk aan Math.max(1, 2, 3), maar je kunt getMaxOfArray() op programmatisch geconstrueerde arrays van elke grootte.

function getMaxOfArray(numArray) {
  return Math.max.apply(null, numArray);
}

Of met de nieuwe spread-operator wordt het een stuk eenvoudiger om het maximale uit een array te halen.

var arr = [1, 2, 3];
var max = Math.max(...arr); // 3
var min = Math.min(...arr); // 1

Antwoord 30

array.sort((a, b) => b - a)[0];

Geeft u de maximale waarde in een reeks getallen.

array.sort((a, b) => a - b)[0];

Geeft u de minimumwaarde in een reeks getallen.

let array = [0,20,45,85,41,5,7,85,90,111];
let maximum = array.sort((a, b) => b - a)[0];
let minimum = array.sort((a, b) => a - b)[0];
console.log(minimum, maximum)

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4 × three =

Other episodes