Как я могу найти наибольшее число, содержащееся в массиве JavaScript?

206

У меня есть простой объект JavaScript Array, содержащий несколько чисел.

[267, 306, 108]

Есть ли функция, которая найдет наибольшее число в этом массиве?

рехнувшийся
источник
22
Math.max(...[267, 306, 108]);
Джексонкр

Ответы:

315

Resig на помощь:

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

Предупреждение : поскольку на некоторых виртуальных машинах максимальное количество аргументов составляет всего 65535 , используйте цикл for, если вы не уверены, что массив настолько мал.

Свежий полумесяц
источник
15
Ах, но теперь к нему прикреплена ТАКАЯ Наклейка Качества только слегка изогнутым способом!
Shog9
2
FWIW, если производительность является фактором в вашем решении, я бы протестировал это по сравнению с вашей собственной легко кодируемой функцией, чтобы убедиться, что она работает хорошо. Мы склонны считать, что нативная реализация будет быстрее; на самом деле, стоимость applyзвонка может очень легко отмыть это.
TJ Crowder
2
Что делать, если длина моего массива превышает предел количества параметров?
lukas.pukenis
3
@CrescentFresh в соответствии с этим: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… жестко задан в 65535. Согласно этому: code.google.com/p/v8/issues/detail?id = 172 и зная, что аргументы помещаются в стек, мы знаем, что он не безграничен
lukas.pukenis
9
Кроме того, этот метод не является надежным. Он потерпит неудачу, если ваш массив больше, чем максимальный размер стека, в результатеRangeError: Maximum call stack size exceeded.
Марк Лундин
197

Вы можете использовать функцию apply, чтобы вызвать Math.max :

var array = [267, 306, 108];
var largest = Math.max.apply(Math, array); // 306

Как это устроено?

Функция apply используется для вызова другой функции с заданным контекстом и аргументами, представленными в виде массива. Функции min и max могут принимать произвольное количество входных аргументов: Math.max (val1, val2, ..., valN)

Так что если мы позвоним:

Math.min.apply(Math, [1,2,3,4]);

Функция apply выполнит:

Math.min(1,2,3,4);

Обратите внимание, что первый параметр, контекст, не важен для этих функций, так как они являются статическими, они будут работать независимо от того, что передается в качестве контекста.

CMS
источник
2
Вау, ты приложил свои ответы с большим усилием: D
ShrekOverflow
1
Замечательно. Но что, если длина моего массива превышает ограничение размера параметра (функции)? Что тогда ?
lukas.pukenis
1
Мне нравится этот ответ лучше, чем другие, потому что он объясняет, что все делает и почему. +1
Марвин
59

Самый простой синтаксис с новым оператором распространения :

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

Источник: Мозилла MDN

искусственный интеллект
источник
2
Тем не менее, как распространение (...), так и применение не удастся или вернет неправильный результат, если массив содержит слишком много элементов developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Green
@ Зеленый FWIW, предел количества параметров составляет 65536 (по крайней мере, в Chrome) ([source ( bugs.webkit.org/show_bug.cgi?id=80797)] ). Поэтому, если в вашем массиве более 65536 элементов, этот ответ не сработает.
mgthomas99
4
65536 должно быть достаточно для всех
vsync
41

Я не эксперт по JS, но я хотел посмотреть, как складываются эти методы, так что это была хорошая практика для меня. Я не знаю, является ли это технически правильным способом тестирования производительности, но я просто запускал их один за другим, как вы можете видеть в моем коде.

Сортировка и получение 0-го значения - безусловно худший метод (и он изменяет порядок вашего массива, что может быть нежелательно). Для остальных разница незначительна, если вы не говорите о миллионах индексов.

Средние результаты пяти прогонов с массивом случайных чисел из 100 000 индексов:

  • сократить взяли 4.0392ms бежать
  • Math.max.apply потребовалось 3,3742 мс для запуска
  • сортировка и получение 0th значение взял 67.4724ms для запуска
  • Math.max в редукторе () потребовалось 6,5804 мсек для запуска
  • пользовательский findmax функция воспринимала 1.6102ms для запуска

var performance = window.performance

function findmax(array)
{
  var max = 0,
      a = array.length,
      counter

  for (counter=0;counter<a;counter++)
  {
      if (array[counter] > max)
      {
          max = array[counter]
      }
  }
  return max
}

function findBiggestNumber(num) {
  var counts = []
  var i
  for (i = 0; i < num; i++) {
    counts.push(Math.random())
  }

  var a, b

  a = performance.now()
  var biggest = counts.reduce(function(highest, count){
        return highest > count ? highest : count
      }, 0)
  b = performance.now()
  console.log('reduce took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest2 = Math.max.apply(Math, counts)
  b = performance.now()
  console.log('Math.max.apply took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest3 = counts.sort(function(a,b){return b-a;})[0]
  b = performance.now()
  console.log('sorting and getting the 0th value took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest4 = counts.reduce(function(highest, count){
        return Math.max(highest,count)
      }, 0)
  b = performance.now()
  console.log('Math.max within reduce() took ' + (b - a) + ' ms to run')

  a = performance.now()
  var biggest5 = findmax(counts)
  b = performance.now()
  console.log('custom findmax function took ' + (b - a) + ' ms to run')
  console.log(biggest + '-' + biggest2 + '-' + biggest3 + '-' + biggest4 + '-' + biggest5)

}

findBiggestNumber(1E5)
redOctober13
источник
7
Для меня это лучший ответ на этот вопрос.
rzelek
1
Я сделал jsperf testsдля вышеупомянутого
vsync
37

Я обнаружил, что для больших массивов (~ 100 тыс. Элементов) на самом деле стоит просто итерировать массив с простым forциклом, выполняя ~ 30% лучше, чем Math.max.apply():

function mymax(a)
{
    var m = -Infinity, i = 0, n = a.length;

    for (; i != n; ++i) {
        if (a[i] > m) {
            m = a[i];
        }
    }

    return m;
}

Результаты тестов

Разъем
источник
3
FWIW, теперь выходит на 84% на Chrome 31.
Илан Бяла
31

Вы можете отсортировать массив в порядке убывания и получить первый элемент:

[267, 306, 108].sort(function(a,b){return b-a;})[0]
гумбо
источник
4
Я предполагаю, что вы также можете просто отсортировать и получить последний элемент ...?
Shog9
@ Shog9: Да, но вам нужно указать функцию сравнения самостоятельно:sort(function(a,b){return b-a;})
Gumbo
9
Ах. Я думал больше как:[...].sort().pop()
Shog9
4
«для поиска числа требуется порядок-n, для сортировки - от порядка (n log n) к порядку (n в квадрате), в зависимости от используемого алгоритма сортировки» - webmasterworld.com/forum91/382.htm
Марко Луглио
2
Также имейте в виду, что это сортирует массив, который может быть или не быть желаемым побочным эффектом. Применение решения является более эффективным и не имеет побочных эффектов.
Калеб
28

Как насчет этого:

var arr = [1,2,3,4];

var largest = arr.reduce(function(x,y){
       return (x > y) ? x : y;
});

console.log(largest);
brroshan
источник
Если бы я сначала увидел этот ответ (в настоящее время внизу списка), я бы сэкономил два часа.
user139301
1
Подход Math.max является, вероятно, самым стандартным, но я получал переполнение стека, когда массив был слишком большим (500 КБ). Этот ответ быстрый и эффективный, и я сам его использовал, так что я голосую за него.
Джей
8

как насчет использования Array.reduce ?

[0,1,2,3,4].reduce(function(previousValue, currentValue){
  return Math.max(previousValue,currentValue);
});
CodeToad
источник
Начальное значение должно быть установлено на -Infinity.
Яцк
@ Джек, зачем это нужно? даже с массивом всех отрицательных чисел, я получаю правильный результат.
CodeToad
1
Это крайний случай, когда массив пуст.
Ja͢ck
5

Почти все ответы используют, Math.max.apply()что приятно и красиво, но имеет ограничения.

Аргументы функции помещаются в стек, который имеет обратную сторону - предел. Так что, если ваш массив больше, чем лимит, он потерпит неудачу сRangeError: Maximum call stack size exceeded.

Чтобы найти размер стека вызовов, я использовал этот код:

var ar = [];
for (var i = 1; i < 100*99999; i++) {
  ar.push(1);
  try {
    var max = Math.max.apply(Math, ar);
  } catch(e) {
    console.log('Limit reached: '+i+' error is: '+e);
    break;
  }
}

Он оказался самым большим на FireFox на моей машине - 591519 . Это означает, что если ваш массив содержит более 591519 элементов, Math.max.apply()это приведет к RangeError .

Лучшее решение этой проблемы - итеративный способ (кредит: https://developer.mozilla.org/ ):

max = -Infinity, min = +Infinity;

for (var i = 0; i < numbers.length; i++) {
  if (numbers[i] > max)
    max = numbers[i];
  if (numbers[i] < min)
    min = numbers[i];
}

Я написал об этом вопросе в своем блоге здесь .

lukas.pukenis
источник
1
Это нечестно. Я хочу получить ответ прямо здесь, на SO, а не на другую ссылку на другой сторонний ресурс. Особенно, когда это сочетается с «все здесь плохо, но иди, смотри, это так здорово в моем блоге ...»
osa
@SergeyOrshanskiy ссылка на стороннюю организацию работает очень хорошо, если она обновляется новыми подсказками и решениями. Также не нужно обижаться. Люди просто хотят решить ваши проблемы тоже. Я тоже хотел это решить, поэтому написал об этом в своем блоге
lukas.pukenis
5

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max

const inputArray = [ 1, 3, 4, 9, 16, 2, 20, 18];
const maxNumber = Math.max(...inputArray);
console.log(maxNumber);

Abhijeet
источник
2
Тем не менее, как распространение (...), так и применение будет либо неудачным, либо вернет неправильный результат, если в массиве слишком много элементов developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Green
5

Найти максимальное и минимальное значение простым и ручным способом. Этот код намного быстрее, чем Math.max.apply; Я пробовал до 1000 тысяч номеров в массиве.

function findmax(array)
{
    var max = 0;
    var a = array.length;
    for (counter=0;counter<a;counter++)
    {
        if (array[counter] > max)
        {
            max = array[counter];
        }
    }
    return max;
}

function findmin(array)
{
    var min = array[0];
    var a = array.length;
    for (counter=0;counter<a;counter++)
    {
        if (array[counter] < min)
        {
            min = array[counter];
        }
    }
    return min;
}
Язер Ранджа
источник
findmax()дает неверный результат, если в массиве есть только отрицательные числа; findmin()дает неверный результат для пустого массива.
Ja͢ck
3

Да, конечно, существуют: Math.max.apply(null,[23,45,67,-45]) и результат возврата 67;

user3702000
источник
3

Простой один лайнер

[].sort().pop()
YasirAzgar
источник
1

Не забывайте, что обертывание может быть сделано Function.prototype.bind, давая вам «все-родную» функцию .

var aMax = Math.max.apply.bind(Math.max, Math);
aMax([1, 2, 3, 4, 5]); // 5
Пол С.
источник
1

Вы также можете расширить Arrayэту функцию и сделать ее частью каждого массива.

Array.prototype.max = function(){return Math.max.apply( Math, this )};
myArray = [1,2,3];

console.log( myArray.max() );
Изз
источник
1
Ужасно неэффективно.
Фрэнк Шмитт
@FrankSchmitt, спасибо, я согласен. Оригинальный ответ не был хорошим решением. Сортировка по умолчанию не сортирует числа, она рассматривает элементы как строки. Отредактировал мой ответ, чтобы иметь правильную сортировку.
Изз
Это была не моя точка зрения. Сортировка массива для нахождения максимума сама по себе ужасно неэффективна, поскольку она требует как минимум N log N операций, тогда как нахождение максимума может быть сделано за N операций.
Фрэнк Шмитт
1

Вы также можете использовать forEach :

var maximum = Number.MIN_SAFE_INTEGER;

var array = [-3, -2, 217, 9, -8, 46];
array.forEach(function(value){
  if(value > maximum) {
    maximum = value;
  }
});

console.log(maximum); // 217

Бенни Нойгебауэр
источник
1

Использование - Array.prototype.reduce()это круто!

[267, 306, 108].reduce((acc,val)=> (acc>val)?acc:val)

где acc = аккумулятор и val = текущее значение ;

var a = [267, 306, 108].reduce((acc,val)=> (acc>val)?acc:val);

console.log(a);

Арора
источник
1

Вы можете попробовать это,

var arr = [267,306,108];
var largestNum = 0;
for(i=0;i<arr.length;i++) {
   if(arr[i]>largest){
    var largest = arr[i];
   }
}
console.log(largest);
Ааша джони
источник
1

Я только начал с JS, но я думаю, что этот метод будет хорош:

var array = [34, 23, 57, 983, 198];<br>
var score = 0;

for(var i = 0; i = array.length; i++) {
  if(array[ i ] > score) {
    score = array[i];
  }
}
Якуб Карки
источник
Это будет иметь проблемы, если arrayсодержит только отрицательные числа.
Teepeemm
0

Найти наибольшее число в многомерном массиве

var max = []; 

for(var i=0; arr.length>i; i++ ){

   var arra = arr[i];
   var largest = Math.max.apply(Math, arra);
   max.push(largest);

   }
return max;
Liveindream
источник
Всегда желательно добавить некоторые подробные пояснения к вашему коду, особенно если уже есть несколько других ответов. Почему этот отличается / лучше?
Bowdzone
@Bowdzone, спасибо за комментарий. этот способ является очень простым, что делает его простым для понимания с небольшим знанием всего лишь нескольких методов.
Liveindream
Это не возвращает наибольшее число, оно возвращает массив наибольшего числа каждого массива в многомерном массиве. Вам необходимо добавить, например var tmax = Math.max.apply(Math, max), или еще лучше использовать функцию закрытия цикла, например, в stackoverflow.com/a/54980012/7438857 . С этой модификацией лучше ответить на отдельный вопрос, как «найти наибольшее число в многомерном массиве», или на stackoverflow.com/questions/32616910/… . WIP: jsfiddle.net/jamesray/3cLu9for/8 .
Джеймс Рэй
stackoverflow.com/a/32617019/7438857 - лучший ответ на правильный вопрос, хотя этот ответ не отвечает на поставленный выше вопрос, он возвращает наибольшее число в каждом массиве в многомерном массиве.
Джеймс Рэй
0

Запустите это:

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

А теперь попробуй [3,10,2].max()возвраты10

RegarBoy
источник
0

Найти максимальное и минимальное значение, используя Bubble Sort

    var arr = [267, 306, 108];

    for(i=0, k=0; i<arr.length; i++) {
      for(j=0; j<i; j++) {
        if(arr[i]>arr[j]) {
          k = arr[i];
          arr[i] = arr[j];
          arr[j] = k;
        }
      }
    }
    console.log('largest Number: '+ arr[0]);
    console.log('Smallest Number: '+ arr[arr.length-1]);

Mano
источник
1
(1) Массивы Javascript уже имеют функцию сортировки O (n log n). (2) Пузырьковая сортировка O (n ^ 2). (3) Нахождение минимума и максимума составляет O (n).
Teepeemm
0

Попробуй это

function largestNum(arr) {
  var currentLongest = arr[0]

  for (var i=0; i< arr.length; i++){
    if (arr[i] > currentLongest){
      currentLongest = arr[i]
    }
  }

  return currentLongest
}
Тоуфик
источник
1
Этот ответ существенно отличается от многих других на этой странице?
Teepeemm
0

В соответствии с комментарием @ Quasimondo , который, по-видимому, в значительной степени упущен, приведенная ниже, похоже, имеет лучшую производительность, как показано здесь: https://jsperf.com/finding-maximum-element-in-an-array . Обратите внимание, что хотя для рассматриваемого массива производительность может не оказать существенного влияния, для больших массивов производительность становится более важной, и, как уже отмечалось, использование Math.max()даже не работает, если длина массива превышает 65535. См. Также этот ответ .

function largestNum(arr) {
    var d = data;
    var m = d[d.length - 1];
    for (var i = d.length - 1; --i > -1;) {
      if (d[i] > m) m = d[i];
    }
    return m;
}
Джеймс Рэй
источник
0

Рекурсивный подход к тому, как это сделать, используя троичные операторы

const findMax = (arr, max, i) => arr.length === i ? max :
  findMax(arr, arr[i] > max ? arr[i] : max, ++i)

const arr = [5, 34, 2, 1, 6, 7, 9, 3];
const max = findMax(arr, arr[0], 0)
console.log(max);

Евгений Сунич
источник
0

Одно for/ofрешение петли:

const numbers = [2, 4, 6, 8, 80, 56, 10];


const findMax = (...numbers) => {
  let currentMax = numbers[0]; // 2

  for (const number of numbers) {
    if (number > currentMax) {
      console.log(number, currentMax);
      currentMax = number;
    }
  }
  console.log('Largest ', currentMax);
  return currentMax;
};

findMax(...numbers);

Миля Миятович
источник