Найти минимальный / максимальный элемент массива в JavaScript
Как я могу легко получить минимальный или максимальный элемент массива JavaScript?
Пример Psuedocode:
let array = [100, 0, 50]
array.min() //=> 0
array.max() //=> 100
61 ответ
Простые вещи, правда.
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());
Поиск элементов Max и Min массива в JavaScript.
Вы можете использовать несколько подходов:
С использованием
Math.min()
и
Math.max()
let array = [100, 0, 50];
Math.min(...array); // 0
Math.max(...array); // 100
С использованиемSorting
let array = [100, 0, 50];
arraySorted = array.toSorted((a, b) => a - b); // [0, 50, 100];
arraySorted.at(0); // 0
arraySorted.at(-1); // 100
Использование простого цикла for
let array = [100, 0, 50];
let maxNumber = array[0];
let minNumber = array[0];
for (let i = 1; i < array.length; i++) {
if (array[i] > maxNumber) {
maxNumber = array[i];
}
if (array[i] < minNumber) {
minNumber = array[i];
}
}
Вы можете использовать методы lodash
_.max([4, 2, 8, 6]);
returns => 8
https://lodash.com/docs/4.17.15
_.min([4, 2, 8, 6]);
returns => 2
С помощью Math.max()
или же Math.min()
Math.max(10, 20); // 20
Math.min(-10, -20); // -20
Следующая функция использует Function.prototype.apply()
найти максимальный элемент в числовом массиве. getMaxOfArray([1, 2, 3])
эквивалентно Math.max(1, 2, 3)
, но вы можете использовать getMaxOfArray()
на программно построенных массивах любого размера.
function getMaxOfArray(numArray) {
return Math.max.apply(null, numArray);
}
Или с новым оператором распространения, получить максимум массива становится намного проще.
var arr = [1, 2, 3];
var max = Math.max(...arr); // 3
var min = Math.min(...arr); // 1
В наши дни (в 2022 году) самый эффективный способ получитьmin
+max
из массива - сделать это за одну итерацию, черезreduce
.
- В JavaScript:
const arr = [3, 0, -2, 5, 9, 4];
const i = arr.reduce((p, c) => {
p.min = c < p.min ? c : p.min ?? c;
p.max = c > p.max ? c : p.max ?? c;
return p;
}, {min: undefined, max: undefined});
console.log(i); //=> { min: -2, max: 9 }
И когда на входе нет данных, он выведет{min: undefined, max: undefined}
.
В TypeScript вы просто добавили бы приведение типов, поэтому возвращаемый тип выводится как{min: number, max: number}
, а не как{min: any, max: any}
:
const arr = [3, 0, -2, 5, 9, 4];
const i = arr.reduce((p, c) => {
p.min = c < p.min ? c : p.min ?? c;
p.max = c > p.max ? c : p.max ?? c;
return p;
}, {min: undefined as number, max: undefined as number});
//=> {min: number, max: number}
console.log(i); //=> { min: -2, max: 9 }
ОБНОВЛЯТЬ
Следующийkiran goud
комментарий, вот альтернатива, которая использует массивы вместо объектов:
const i = arr.reduce((p, c) => {
p[0] = c < p[0] ? c : p[0] ?? c;
p[1] = c > p[1] ? c : p[1] ?? c;
return p;
}, [undefined, undefined]);
console.log(i); //=> [-2, 9]
Пытаться
let max= a=> a.reduce((m,x)=> m>x ? m:x);
let min= a=> a.reduce((m,x)=> m<x ? m:x);
let max= a=> a.reduce((m,x)=> m>x ? m:x);
let min= a=> a.reduce((m,x)=> m<x ? m:x);
// TEST - pixel buffer
let arr = Array(200*800*4).fill(0);
arr.forEach((x,i)=> arr[i]=100-i%101);
console.log('Max', max(arr));
console.log('Min', min(arr))
Для Math.min/max (+apply) получаем ошибку:
Превышен максимальный размер стека вызовов (Chrome 74.0.3729.131)
// TEST - pixel buffer
let arr = Array(200*800*4).fill(0);
arr.forEach((x,i)=> arr[i]=100-i%101);
// Exception: Maximum call stack size exceeded
try {
let max1= Math.max(...arr);
} catch(e) { console.error('Math.max :', e.message) }
try {
let max2= Math.max.apply(null, arr);
} catch(e) { console.error('Math.max.apply :', e.message) }
// same for min
Если вы используете библиотеку sugar.js, вы можете написать arr.min() и arr.max(), как вы предлагаете. Вы также можете получить минимальное и максимальное значения из нечисловых массивов.
min ( map, all = false) Возвращает элемент в массиве с наименьшим значением. map может быть функцией, отображающей проверяемое значение, или строкой, действующей как ярлык. Если все верно, вернет все минимальные значения в массиве.
max ( map, all = false) Возвращает элемент в массиве с наибольшим значением. map может быть функцией, отображающей проверяемое значение, или строкой, действующей как ярлык. Если все верно, вернет все максимальные значения в массиве.
Примеры:
[1,2,3].min() == 1
['fee','fo','fum'].min('length') == "fo"
['fee','fo','fum'].min('length', true) == ["fo"]
['fee','fo','fum'].min(function(n) { return n.length; }); == "fo"
[{a:3,a:2}].min(function(n) { return n['a']; }) == {"a":2}
['fee','fo','fum'].max('length', true) == ["fee","fum"]
Такие библиотеки, как Lo-Dash и underscore.js, также предоставляют аналогичные мощные функции min и max:
Пример из Lo-Dash:
_.max([4, 2, 8, 6]) == 8
var characters = [
{ 'name': 'barney', 'age': 36 },
{ 'name': 'fred', 'age': 40 }
];
_.max(characters, function(chr) { return chr.age; }) == { 'name': 'fred', 'age': 40 }
Решение ChaosPandion работает, если вы используете прототип. Если нет, подумайте об этом:
Array.max = function( array ){
return Math.max.apply( Math, array );
};
Array.min = function( array ){
return Math.min.apply( Math, array );
};
Выше будет возвращать NaN, если значение массива не является целым числом, поэтому вы должны построить некоторые функции, чтобы избежать этого. В противном случае это будет работать.
Если вы используете framework-файл prototype.js, то этот код будет работать нормально:
arr.min();
arr.max();
Документально здесь: Javascript прототип фреймворка для макс.
let arr = [2,5,3,5,6,7,1];
let max = Math.max(...arr); // 7
let min = Math.min(...arr); // 1
Вот простой ванильный подход JS.
function getMinArrayVal(seq){
var minVal = seq[0];
for(var i = 0; i<seq.length-1; i++){
if(minVal < seq[i+1]){
continue;
} else {
minVal = seq[i+1];
}
}
return minVal;
}
minHeight = Math.min.apply({},YourArray);
minKey = getCertainKey(YourArray,minHeight);
maxHeight = Math.max.apply({},YourArray);
maxKey = getCertainKey(YourArray,minHeight);
function getCertainKey(array,certainValue){
for(var key in array){
if (array[key]==certainValue)
return key;
}
}
Вы можете использовать Array.sort, но вам придется написать простую функцию сортировки чисел, так как по умолчанию используется алфавитный порядок.
Тогда вы можете взять arr[0]
а также arr[arr.length-1]
чтобы получить мин и макс.
Прочитав все ответы, я подумал, что было бы хорошо написать самое надежное решение (которое здесь не было предоставлено), с которым я столкнулся. Если ваш массив значений может вырасти до десятков тысяч, используйте гибридную стратегию: применяйте свою функцию одновременно к фрагментам массива:
function minOfArray(arr) {
var min = Infinity;
var QUANTUM = 32768;
for (var i = 0, len = arr.length; i < len; i += QUANTUM) {
var submin = Math.min.apply(null,
arr.slice(i, Math.min(i+QUANTUM, len)));
min = Math.min(submin, min);
}
return min;
}
var min = minOfArray([5, 6, 2, 3, 7]);
Источник: MDN
хорошо, я хотел бы сделать это следующим образом
const findMaxAndMin = (arr) => {
if (arr.length <= 0) return -1;
let min = arr[0];
let max = arr[0];
arr.map((n) => {
n > max ? (max = n) : false;
n < min ? (min = n) : false;
});
return [min, max];
};
Мне нравится подход Линуса Reduce(), особенно для больших массивов. Но если вы знаете, что вам нужны и min, и max, зачем перебирать массив дважды?
Array.prototype.minmax = function () {
return this.reduce(function (p, v) {
return [(p[0] < v ? p[0] : v), (p[1] > v ? p[1] : v)];
}, [this[0], this[0]]);
}
Конечно, если вы предпочитаете итеративный подход, вы можете сделать это тоже:
Array.prototype.minmax = function () {
var mn = this[0], mx = this[0];
this.forEach(function (v) {
if (v < mn) mn = v;
if (v > mx) mx = v;
});
return [mn, mx];
};
Другое решение
let arr = [1,10,25,15,31,5,7,101];
let sortedArr = arr.sort((a, b) => a - b)
let min = sortedArr[0];
let max = sortedArr[arr.length-1]
console.log(`min => ${min}. Max => ${max}`)
Чтобы "max" и "min" не были перечислены в цикле "for ... in":
Object.defineProperty(Array.prototype, "max", {
enumerable: false,
configurable: false,
writable: false,
value: function() {
return Math.max.apply(null, this);
}
});
Object.defineProperty(Array.prototype, "min", {
enumerable: false,
configurable: false,
writable: false,
value: function() {
return Math.min.apply(null, this);
}
});
Использование:
var x = [10,23,44,21,5];
x.max(); //44
x.min(); //5
Создать простой объект
var myArray = new Array();
myArray = [10,12,14,100];
var getMaxHeight = {
hight : function( array ){ return Math.max.apply( Math, array );
}
getMaxHeight.hight(myArray);
Чтобы добавить ко многим хорошим ответам здесь, вот версия машинописного текста, которая может обрабатывать списки, где некоторые значенияundefined
.
Как это можно использовать:
const testDates = [
undefined,
new Date('July 30, 1986'),
new Date('July 31, 1986'),
new Date('August 1, 1986'),
]
const max: Date|undefined = arrayMax(testDates); // Fri Aug 01 1986
const min: Date|undefined = arrayMin(testDates); // Min: Wed Jul 30 1986
const test: Date = arrayMin(testDates); // Static type error
const anotherTest: undefined = arrayMin(testDates); // Static type error
Определения (т.notEmpty
определение взято из этого поста ):
function arrayMax<T>(values?: (T | null | undefined)[]): T | undefined {
const nonEmptyValues = filterEmpty(values);
if (nonEmptyValues.length === 0) {
return undefined;
}
return nonEmptyValues.reduce((a, b) => (a >= b ? a : b), nonEmptyValues[0]);
}
function arrayMin<T>(values?: (T | null | undefined)[]): T | undefined {
const nonEmptyValues = filterEmpty(values);
if (nonEmptyValues.length === 0) {
return undefined;
}
return nonEmptyValues.reduce((a, b) => (a <= b ? a : b), nonEmptyValues[0]);
}
function filterEmpty<T>(values?: (T | null | undefined)[] | null): T[] {
return values?.filter(notEmpty) ?? [];
}
function notEmpty<T>(value: T | null | undefined): value is T {
if (value === null || value === undefined) return false;
const testDummy: T = value;
return true;
}
я не использовалMath.max
как предложено в документации, потому что таким образом я могу использовать эту функцию с любыми сопоставимыми объектами (если вы знаете, как это ввести, дайте мне знать, чтобы я мог лучше определитьT
).
У меня ниже скрипт работает в ndoejs:
var numbers = [1, 2, 3, 4];
console.log('Value:: ' + Math.max.apply(null, numbers) ); // 4
Возможно, вы не захотите добавлять методы в прототип Array, которые могут конфликтовать с другими библиотеками.
Я видел множество примеров использования forEach, которые я бы не рекомендовал для больших массивов из-за его низкой производительности по сравнению с циклом for. https://coderwall.com/p/kvzbpa/don-t-use-array-foreach-use-for-instead
Также Math.max(Math, [1,2,3]);
Всегда дает мне NaN?
function minArray(a) {
var min=a[0]; for(var i=0,j=a.length;i<j;i++){min=a[i]<min?a[i]:min;}
return min;
}
function maxArray(a) {
var max=a[0]; for(var i=0,j=a.length;i<j;i++){max=a[i]>max?a[i]:max;}
return max;
}
minArray([1,2,3]); // returns 1
Если у вас есть массив объектов, приведенный ниже пример функции minArray() будет принимать 2 параметра, первый - это массив, а второй - имя ключа для сравнения значения ключа объекта. Функция в этом случае будет возвращать индекс массива, который имеет наименьшее значение ключа.
function minArray(a, key) {
var min, i, j, index=0;
if(!key) {
min=a[0];
for(i=0,j=a.length;i<j;i++){min=a[i]<min?a[i]:min;}
return min;
}
min=a[0][key];
for(i=0,j=a.length;i<j;i++){
if(a[i][key]<min) {
min = a[i][key];
index = i;
}
}
return index;
}
var a = [{fee: 9}, {fee: 2}, {fee: 5}];
minArray(a, "fee"); // returns 1, as 1 is the proper array index for the 2nd array element.
Если у вас есть сложный объект, вы можете использовать сортировку.... например: если я хочу получить элемент, который содержит значение MAX/MIN ниже objs.
var objs= [
{name:"Apple",value:3},
{name:"Love",value:32},
{name:"Cheese",value:1},
{name:"Pork",value:77},
{name:"Xmas",value:99}
];
Я сделаю вид:
objs.sort(function(a, b){return a.value-b.value});
Затем:objs[0]
это мин, objs[objs.length-1]
это Макс.
Альтернативные Солны
class SmallestIntegerFinder {
findSmallestInt(args) {
return args.reduce((min,item)=>{ return (min<item ? min : item)});
}
}
class SmallestIntegerFinder {
findSmallestInt(args) {
return Math.min(...args)
}
}
class SmallestIntegerFinder {
findSmallestInt(args) {
return Math.min.apply(null, args);
}
}
class SmallestIntegerFinder {
findSmallestInt(args) {
args.sort(function(a, b) {
return a - b; } )
return args[0];
}
}
Вставьте числа, разделенные запятой, и нажмите на событие, которое вы хотите вызвать, т.е. получите максимальное или минимальное число.
function maximumNumber() {
var numberValue = document.myForm.number.value.split(",");
var numberArray = [];
for (var i = 0, len = numberValue.length; i < len; i += 1) {
numberArray.push(+numberValue[i]);
var largestNumber = numberArray.reduce(function (x, y) {
return (x > y) ? x : y;
});
}
document.getElementById("numberOutput").value = largestNumber;
}
function minimumNumber() {
var numberValue = document.myForm.number.value.split(",");
var numberArray = [];
for (var i = 0, len = numberValue.length; i < len; i += 1) {
numberArray.push(+numberValue[i]);
var smallestNumber = numberArray.reduce(function (x, y) {
return (x < y) ? x : y;
});
}
document.getElementById("numberOutput").value = smallestNumber;
}
function restrictCharacters(evt) {
evt = (evt) ? evt : window.event;
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (((charCode >= '48') && (charCode <= '57')) || (charCode == '44')) {
return true;
}
else {
return false;
}
}
<div>
<form name="myForm">
<table>
<tr>
<td>Insert Number</td>
<td><input type="text" name="number" id="number" onkeypress="return restrictCharacters(event);" /></td>
<td><input type="button" value="Maximum" onclick="maximumNumber();" /></td>
<td><input type="button" value="Minimum" onclick="minimumNumber();"/></td>
<td><input type="text" id="numberOutput" name="numberOutput" /></td>
</tr>
</table>
</form>
</div>
В целях обучения вы можете сделать это, используя переменные и цикл for без использования встроенных функций.
Линейный, почти чисто функциональный подход
var min=[0, 29, 25].map((function(max) {max=-Infinity; return function(e) {return max=Math.max(max, e);}})())[0]
Больше примеров:
Нахождение минимального значения
function getMin(arr) {
return (ar || [0, 29, 25]).
map((function(max) {max=-Infinity; return function(e) {return max=Math.max(max, e);}})())[0];
}
или используя Array.map
метод с переменным замыканием
function getMin(arrObjs) {
return (arrObjs || [{val: 0}, {val: 29}, {val: 25}]).
map((function(max) {max=-Infinity; return function(e) {return max=(max.val>e.val?max:e);}})())[0];
}
Определение максимального значения
function getMax(arr) {
return (ar || [0, 29, 25]).
map((function(v) {v=Infinity; return function(e) {return v=Math.min(v, e);}})())[0];
}
для массива объектов
function getMax(arrObjs) {
return (arrObjs || [{val: 0}, {val: 29}, {val: 25}]).
map((function(v) {v=-Infinity; return function(e) {return v=(v.val<e.val?v:e);}})())[0];
}
Если вам нужна производительность, то это лучший способ для небольших массивов:
var min = 99999;
var max = 0;
for(var i = 0; i < v.length; i++)
{
if(v[i] < min)
{
min = v[i];
}
if(v[i] >= max)
{
max = v[i];
}
}
Рекурсивное решение проблемы
const findMinMax = (arr, max, min, i) => arr.length === i ? {
min,
max
} :
findMinMax(
arr,
arr[i] > max ? arr[i] : max,
arr[i] < min ? arr[i] : min,
++i)
const arr = [5, 34, 2, 1, 6, 7, 9, 3];
const max = findMinMax(arr, arr[0], arr[1], 0)
console.log(max);
Вот еще один пример. Рассчитайте значение Max/Min из массива с помощью lodash.
let array = [100, 0, 50];
var func = _.over(Math.max, Math.min);
var [max, min] = func(...array);
// => [100, 0]
console.log(max);
console.log(min);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>