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 aanMath.max(1, 2, 3)
, maar je kuntgetMaxOfArray()
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:
- discrete oplossing: een FOR-lus om elk element van de array te vergelijken met de huidige max- en/of min-waarde;
- APPLY-oplossing: de array verzenden naar de interne functies Math.max en/of Math.min met behulp van apply(null,array);
- 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:
- Discrete oplossing: mean=0.161s, sd=0.078
- OPLOSSING TOEPASSEN: mean=3.571s, sd=0.487
- 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)