ฉันจะค้นหาหมายเลขที่ใหญ่ที่สุดในอาร์เรย์ JavaScript ได้อย่างไร


206

ฉันมีอ็อบเจกต์ JavaScript Array อย่างง่าย ๆ ที่มีตัวเลขไม่กี่ตัว

[267, 306, 108]

มีฟังก์ชั่นที่จะหาจำนวนมากที่สุดในอาเรย์นี้หรือไม่?


22
Math.max(...[267, 306, 108]);
Jacksonkr

คำตอบ:


315

Resig เพื่อช่วยเหลือ:

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

คำเตือน : เนื่องจากจำนวนอาร์กิวเมนต์สูงสุดมีน้อยถึง 65535 ใน VMs บางตัวใช้สำหรับลูปถ้าคุณไม่แน่ใจว่าอาร์เรย์มีขนาดเล็ก


15
อ่า แต่ตอนนี้มันมีสติกเกอร์ SO of Qualityติดอยู่ในแฟชั่นที่ดูคดเล็กน้อยเท่านั้น!
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
นอกจากนี้วิธีนี้ยังไม่สมบูรณ์ มันจะล้มเหลวถ้าอาเรย์ของคุณมีขนาดใหญ่กว่าขนาดสแต็ค mamximum ที่เกิดขึ้นRangeError: Maximum call stack size exceeded.
Mark Lundin

197

คุณสามารถใช้ฟังก์ชั่นนำไปใช้เพื่อโทรMath.max :

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

มันทำงานอย่างไร?

ใช้ฟังก์ชั่นที่ใช้ในการเรียกใช้ฟังก์ชันอีกด้วยบริบทที่กำหนดและข้อโต้แย้งให้เป็นอาร์เรย์ ฟังก์ชัน min และ max สามารถรับจำนวนอาร์กิวเมนต์ที่ป้อนเข้าโดยพลการได้: Math.max (val1, val2, ... , valN)

ดังนั้นถ้าเราเรียกว่า:

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

ฟังก์ชั่นใช้จะดำเนินการ:

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

โปรดทราบว่าพารามิเตอร์แรกบริบทไม่สำคัญสำหรับฟังก์ชั่นเหล่านี้เนื่องจากพวกเขาเป็นแบบคงที่พวกเขาจะทำงานโดยไม่คำนึงถึงสิ่งที่จะถูกส่งผ่านเป็นบริบท


2
คุณใส่คำตอบของคุณด้วยความพยายามอย่างมาก: D
ShrekOverflow

1
เยี่ยมมาก แต่จะเกิดอะไรขึ้นถ้าความยาวของอาร์เรย์ของฉันเกินขีด จำกัด ขนาดพารามิเตอร์ (ของฟังก์ชัน) ถ้าเช่นนั้นจะเป็นอย่างไร
lukas.pukenis

1
ฉันชอบคำตอบนี้ดีกว่าคนอื่นเพราะมันอธิบายว่าทุกอย่างทำอะไรและทำไม +1
Marvin

59

ไวยากรณ์ที่ง่ายที่สุดด้วยตัวดำเนินการสเปรดใหม่:

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

ที่มา: Mozilla MDN


2
อย่างไรก็ตามทั้งสเปรด (... ) และการใช้จะล้มเหลวหรือส่งคืนผลลัพธ์ที่ผิดถ้าอาร์เรย์มีองค์ประกอบมากเกินไป developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ …
Green

@Green FWIW ขีด จำกัด การนับพารามิเตอร์คือ 65536 (อย่างน้อยใน Chrome) ([แหล่งที่มา ( bugs.webkit.org/show_bug.cgi?id=80797)] ) ดังนั้นถ้าอาร์เรย์ของคุณมีองค์ประกอบมากกว่า 65536 คำตอบนี้จะไม่ทำงาน
mgthomas99

4
65536 ควรจะเพียงพอสำหรับทุกคน
vsync

41

ฉันไม่ใช่ผู้เชี่ยวชาญ JS แต่ฉันต้องการดูว่าวิธีการเหล่านี้ซ้อนกันอย่างไรนี่เป็นวิธีปฏิบัติที่ดีสำหรับฉัน ฉันไม่รู้ว่านี่เป็นเทคนิคที่เหมาะสมในการทดสอบประสิทธิภาพเหล่านี้หรือไม่ แต่ฉันเพิ่งลองทดสอบพวกเขาทีละอย่างตามที่คุณเห็นในรหัสของฉัน

การเรียงลำดับและรับค่า 0 เป็นวิธีที่แย่ที่สุด (และจะปรับเปลี่ยนลำดับของอาร์เรย์ซึ่งอาจไม่เป็นที่ต้องการ) สำหรับคนอื่น ๆ ความแตกต่างนั้นเล็กน้อยมากยกเว้นว่าคุณกำลังพูดถึงดัชนีนับล้าน

ผลลัพธ์โดยเฉลี่ยของการรันห้าครั้งด้วยอาเรย์ 100,000 ดัชนีของตัวเลขสุ่ม:

  • ลดใช้4.0392msในการทำงาน
  • Math.max.apply ใช้เวลา3.3742msในการเรียกใช้
  • การเรียงลำดับและรับค่า 0 นั้นใช้เวลา67.4724msในการรัน
  • Math.max ในการลด () ใช้เวลา6.5804 มิลลิวินาทีในการเรียกใช้
  • ฟังก์ชัน findmax ที่กำหนดเองใช้เวลา1.6102 มิลลิวินาทีในการเรียกใช้

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)

7
สำหรับฉันนี่คือคำตอบที่ดีที่สุดสำหรับคำถามนี้
rzelek

1
ฉันได้ทำjsperf testsสำหรับข้างต้น
vsync

37

ฉันได้พบว่าสำหรับอาร์เรย์ที่ใหญ่กว่า (องค์ประกอบประมาณ ~ 100k) มันจ่ายจริง ๆ เพียงแค่วนซ้ำอาร์เรย์ด้วย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
Ilan Biala

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 บันทึก n) ถึงการสั่งซื้อ (n กำลังสอง), ขึ้นอยู่กับอัลกอริทึมการเรียงลำดับที่ใช้" - webmasterworld.com/forum91/382.htm
Marco Luglio

2
นอกจากนี้โปรดทราบว่าสิ่งนี้จะจัดเรียงอาเรย์ซึ่งอาจเป็นหรือไม่เป็นผลข้างเคียงที่ต้องการ โซลูชันที่ใช้นั้นมีประสิทธิภาพดีกว่าและไม่มีผลข้างเคียง
Caleb

28

เกี่ยวกับสิ่งนี้:

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

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

console.log(largest);

ถ้าฉันเห็นคำตอบนี้ก่อน (ปัจจุบันที่ด้านล่างของรายการ) ฉันจะได้รับการบันทึกสองชั่วโมง
139301

1
วิธีการ Math.max น่าจะเป็นมาตรฐานมากที่สุด แต่ฉันได้รับสแต็คล้นเมื่ออาเรย์มีขนาดใหญ่เกินไป (500K) คำตอบนี้รวดเร็วและมีประสิทธิภาพและเป็นคำตอบที่ฉันใช้ด้วยตัวเองดังนั้นฉันจึงพยายามแก้ปัญหานี้
Jay

8

วิธีการเกี่ยวกับการใช้Array.reduce ?

[0,1,2,3,4].reduce(function(previousValue, currentValue){
  return Math.max(previousValue,currentValue);
});

-Infinityค่าเริ่มต้นควรจะกำหนดให้
Ja͢ck

@ แจ็คทำไมถึงเป็นสิ่งจำเป็น แม้จะมีอาร์เรย์ของจำนวนลบทั้งหมดฉันก็ได้ผลลัพธ์ที่ถูกต้อง
CodeToad

1
มันคือกรณีขอบโดยที่อาร์เรย์ว่างเปล่า
แจ็ค

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 ซึ่งหมายความว่าถ้าคุณอาเรย์ที่มีมากกว่า591,519รายการ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];
}

ผมได้เขียนเกี่ยวกับคำถามนี้ในบล็อกของฉันที่นี่


1
สิ่งนี้ไม่ยุติธรรม ฉันต้องการคำตอบได้ที่นี่ใน SO ไม่ใช่ลิงก์อื่นไปยังแหล่งข้อมูลอื่นของบุคคลที่สาม โดยเฉพาะอย่างยิ่งเมื่อมันรวมกับ "ทุกอย่างที่นี่ไม่ดี แต่ไปดูมันยอดเยี่ยมมากในบล็อกของฉัน ... "
osa

@SergeyOrshanskiy ลิงก์ไปยังบุคคลที่สามทำงานได้เป็นอย่างดีในกรณีที่มีการอัปเดตด้วย insigths และโซลูชั่นใหม่ ยังไม่จำเป็นต้องรู้สึกขุ่นเคือง ผู้คนแค่ต้องการแก้ปัญหาของคุณด้วย ฉันต้องการแก้ไขด้วยดังนั้นฉันจึงเขียนเกี่ยวกับเรื่องนี้ในบล็อกของฉัน
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);


2
อย่างไรก็ตามทั้งสเปรด (... ) และการใช้จะล้มเหลวหรือส่งคืนผลลัพธ์ที่ผิดถ้าอาร์เรย์มีองค์ประกอบมากเกินไป developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ …
Green

5

การหาค่าสูงสุดและต่ำสุดวิธีที่ง่ายและคู่มือ รหัสนี้เร็วกว่าMath.max.applyมาก ฉันได้ลองตัวเลขมากถึง 1,000,000 ชุด

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

4

ในการหาจำนวนที่มากที่สุดในอาเรย์ที่คุณต้องการใช้งานMath.max(...arrayName);มันจะเป็นดังนี้

let myArr = [1, 2, 3, 4, 5, 6];
console.log(Math.max(...myArr));

หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับMath.max: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max




1

อย่าลืมว่าห่อสามารถทำได้ด้วยการFunction.prototype.bindให้คุณ "all-พื้นเมือง" ฟังก์ชั่น

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
ไม่มีประสิทธิภาพมากนัก
Frank Schmitt

@ FrankSchmitt ขอขอบคุณฉันเห็นด้วย คำตอบเดิมไม่ใช่ทางออกที่ดี เรียงตามค่าเริ่มต้นไม่เรียงลำดับหมายเลขมันจะถือว่าองค์ประกอบเป็นสตริง แก้ไขคำตอบของฉันเพื่อให้เรียงลำดับที่ถูกต้อง
Izz

นั่นไม่ใช่จุดของฉัน การเรียงลำดับอาเรย์เพื่อค้นหาค่าสูงสุดนั้นไม่มีประสิทธิภาพมากนักเพราะมันต้องใช้การดำเนินการอย่างน้อย N log N ในขณะที่การค้นหาค่าสูงสุดสามารถทำได้ในการดำเนินการ N
Frank Schmitt


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;

ขอแนะนำให้เพิ่มคำอธิบายที่ซับซ้อนลงในโค้ดของคุณเสมอโดยเฉพาะอย่างยิ่งหากมีคำตอบอื่น ๆ อีกมากมายอยู่แล้ว ทำไมสิ่งนี้จึงแตกต่าง / ดีกว่า
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
James Ray

stackoverflow.com/a/32617019/7438857เป็นคำตอบที่ดีกว่าสำหรับคำถามที่ถูกต้องในขณะที่คำตอบนี้ไม่ได้ตอบคำถามข้างต้นมันจะส่งกลับจำนวนที่ใหญ่ที่สุดในแต่ละอาร์เรย์ภายในอาร์เรย์หลายมิติ
James Ray

0

เรียกใช้สิ่งนี้:

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

และตอนนี้ลอง[3,10,2].max()ส่งคืน10


0

ค้นหาค่า Max และ Min โดยใช้ 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]);


1
(1) อาร์เรย์ Javascript มีฟังก์ชั่นการเรียง O (n log n) อยู่แล้ว (2) Bubble sort คือ O (n ^ 2) (3) การค้นหา min และ max คือ 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);

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.