ฉันจะได้รับองค์ประกอบ min หรือ max ของ JavaScript Array ได้อย่างง่ายดายได้อย่างไร?
ตัวอย่าง Psuedocode:
let array = [100, 0, 50]
array.min() //=> 0
array.max() //=> 100
Math.max.apply(null, [2,5,16,1])
ฉันจะได้รับองค์ประกอบ min หรือ max ของ JavaScript Array ได้อย่างง่ายดายได้อย่างไร?
ตัวอย่าง Psuedocode:
let array = [100, 0, 50]
array.min() //=> 0
array.max() //=> 100
Math.max.apply(null, [2,5,16,1])
คำตอบ:
วิธีการเพิ่มวัตถุ Array ในตัวให้ใช้Math.max
/ Math.min
แทน:
Array.prototype.max = function() {
return Math.max.apply(null, this);
};
Array.prototype.min = function() {
return Math.min.apply(null, this);
};
ขยายตัว ins สามารถทำให้เกิดการชนกับห้องสมุดอื่น ๆ (เห็นบางส่วน) ดังนั้นคุณอาจจะสะดวกสบายมากขึ้นมีเพียงapply
'ไอเอ็นจีMath.xxx()
ไปยังอาร์เรย์ของคุณโดยตรง:
var min = Math.min.apply(null, arr),
max = Math.max.apply(null, arr);
อีกทางหนึ่งสมมติว่าเบราว์เซอร์ของคุณรองรับ ECMAScript 6 คุณสามารถใช้ตัวดำเนินการสเปรดซึ่งทำหน้าที่คล้ายกับapply
วิธีการ:
var min = Math.min( ...arr ),
max = Math.max( ...arr );
null
หรือMath
หรือ{}
อะไรก็ตามที่มีapply()
หรือcall()
ไม่มีผลต่อ Math.max
ไม่ควรและไม่ควรอ้างอิงthis
ภายใน
Math.max.apply(null, $.makeArray(array));
.max
หรือ.min
วิธีการในอนาคต สถานการณ์ที่สมจริงสมบูรณ์แบบ: คุณใช้คำตอบนี้ ในปี 2016 หรือ ES7 ES8 ข้อมูลจำเพาะและArray.max
Array.min
ต่างจากรุ่นนี้พวกมันทำงานบนสตริง เพื่อนร่วมงานในอนาคตของคุณพยายามรับสตริงตัวอักษรล่าสุดในอาร์เรย์ด้วย.max()
วิธีการเนทีฟที่ได้รับการNaN
บันทึกไว้อย่างดี แต่ได้มาอย่างลึกลับ ชั่วโมงต่อมาเธอพบรหัสนี้เรียกใช้git blame
และสาปแช่งชื่อของคุณ
var max_of_array = Math.max.apply(Math, array);
สำหรับดูการอภิปรายเต็ม: http://aaroncrane.co.uk/2008/11/javascript_max_api/
Math.max.apply(Math, array)
และMath.max.apply(null, array)
คืออะไร? บล็อกบอกว่า "... คุณต้องพูดซ้ำ ๆ ซ้ำอีกครั้งว่าmax
เป็นของMath
... " แต่ดูเหมือนว่าฉันไม่จำเป็นต้องทำเช่นนั้น (โดยตั้งค่าอาร์กิวเมนต์แรกapply
เป็นnull
)
Math.max(a,b)
, Math
จะถูกส่งเป็นค่าดังนั้นจึงอาจจะทำให้ความรู้สึกที่จะทำเช่นเดียวกันกับเมื่อโทรthis
apply
แต่Math.max
ไม่ใช้this
ค่าเพื่อให้คุณสามารถส่งผ่านค่าที่คุณต้องการ
สำหรับอาร์เรย์ขนาดใหญ่ (องค์ประกอบ ~ 10⁷) Math.min
และMath.max
ทั้งคู่สร้างข้อผิดพลาดต่อไปนี้ใน Node.js
RangeError: เกินขนาดสแต็กการโทรสูงสุด
โซลูชันที่มีประสิทธิภาพมากขึ้นคือการไม่เพิ่มอิลิเมนต์ทุกตัวใน call stack แต่แทนที่จะส่งผ่านอาร์เรย์:
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 );
});
}
หากคุณกังวลเกี่ยวกับความเร็วรหัสต่อไปนี้คือ ~ 3 ครั้งเร็วขึ้นแล้วก็Math.max.apply
คือในคอมพิวเตอร์ของฉัน ดู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;
};
หากอาร์เรย์ของคุณมีสตริงแทนตัวเลขคุณจะต้องบังคับให้เป็นตัวเลข โค้ดด้านล่างทำเช่นนั้น แต่จะทำให้โค้ดช้าลง ~ 10 ครั้งในเครื่องของฉัน ดู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;
};
min
และmax
องค์ประกอบสุดท้ายและลดการวนซ้ำตาม 1 ( while(--len)
);)
very different results
คุณทำสิ่งนี้ 5 ปีต่อมา)
reduce
แก้ปัญหาช้าที่สุด แม้ว่าคุณจะทำงานกับอาร์เรย์ที่มีนับล้านขององค์ประกอบมันเป็นดีกว่าการใช้มาตรฐานสำหรับวง ดูคำตอบของฉันมากขึ้น
การใช้สเปรดโอเปอเรเตอร์ (ES6)
Math.max(...array); // the same with "min" => Math.min(...array);
If no arguments are given, the result is -∞.
// 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 ในMath.max()
แล้วครอบคลุมปัญหานี้:
ฟังก์ชันต่อไปนี้ใช้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);
ตาม MDNapply
และการแพร่กระจายการแก้ปัญหาที่มีข้อ จำกัด ของ 65536 ที่มาจากการ จำกัด จำนวนสูงสุดของการขัดแย้งนี้:
แต่ระวัง: ในการใช้งานด้วยวิธีนี้คุณจะเสี่ยงเกินขีดจำกัดความยาวอาร์กิวเมนต์ของเครื่องมือ JavaScript ผลที่ตามมาของการใช้ฟังก์ชั่นที่มีข้อโต้แย้งมากเกินไป (คิดว่ามากกว่าหนึ่งหมื่นข้อโต้แย้ง) จะแตกต่างกันไปตามเอ็นจิ้น ( JavaScriptCore มีการ จำกัด อาร์กิวเมนต์แบบตายตัวจำนวน 65536 ) เนื่องจากขีด จำกัด (แน่นอนแม้กระทั่งธรรมชาติของกองซ้อนขนาดใหญ่ พฤติกรรม) ไม่ได้ระบุ เครื่องมือบางอย่างจะทำให้เกิดข้อยกเว้น ผู้อื่นจะ จำกัด จำนวนของข้อโต้แย้งที่ส่งผ่านไปยังฟังก์ชันที่ใช้อย่างไม่เป็นอันตราย เพื่อแสดงให้เห็นถึงกรณีหลังนี้: หากเครื่องยนต์มีขีด จำกัด สี่ข้อโต้แย้ง (ขีด จำกัด ที่แท้จริงมีค่าสูงกว่าอย่างมีนัยสำคัญ) มันจะเหมือนกับว่าข้อโต้แย้ง 5, 6, 2, 3 ถูกส่งผ่านไปใช้ในตัวอย่างด้านบน มากกว่าอาร์เรย์เต็ม
พวกเขายังให้บริการโซลูชั่นแบบไฮบริดซึ่งไม่ได้มีประสิทธิภาพที่ดีเมื่อเทียบกับโซลูชั่นอื่น ๆ ดูการทดสอบประสิทธิภาพด้านล่างเพิ่มเติม
ใน 2019 วงเงินที่เกิดขึ้นจริงเป็นขนาดสูงสุดของสาย stack สำหรับโครเมี่ยมตามเดสก์ทอปเบราว์เซอร์ที่ทันสมัยที่นี้หมายถึงว่าเมื่อมันมาถึงการหา min max / กับapply
หรือการแพร่กระจายจริงขนาดสูงสุดของตัวเลขเท่านั้นอาร์เรย์เป็น ~ เหนือสิ่งนี้จะมีสแต็คล้นและข้อผิดพลาดต่อไปนี้จะถูกโยน:
RangeError: เกินขนาดสแต็กการโทรสูงสุด
ด้วยสคริปต์ด้านล่าง (ตามการโพสต์บล็อกนี้ ) โดยการจับข้อผิดพลาดนั้นคุณสามารถคำนวณขีด จำกัด สำหรับสภาพแวดล้อมเฉพาะของคุณ
คำเตือน! การเรียกใช้สคริปต์นี้ต้องใช้เวลาและขึ้นอยู่กับประสิทธิภาพของระบบของคุณอาจทำให้เบราว์เซอร์หรือระบบของคุณช้าหรือขัดข้อง!
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;
}
}
จากการทดสอบในความคิดเห็นของEscapeNetscapeฉันได้สร้างเกณฑ์มาตรฐานบางอย่างที่ทดสอบ 5 วิธีที่แตกต่างกันในอาเรย์ตัวเลขสุ่มเท่านั้นที่มีรายการ 100,000 รายการรายการ
ในปี 2019 ผลลัพธ์แสดงให้เห็นว่าการวนซ้ำมาตรฐาน (ซึ่ง BTW ไม่มีขนาด จำกัด ) นั้นเร็วที่สุดในทุกที่ apply
และแพร่กระจายอย่างใกล้ชิดหลังจากนั้นจากนั้นโซลูชันไฮบริดของ MDN ในเวลาต่อมาreduce
ช้าที่สุด
การทดสอบเกือบทั้งหมดให้ผลลัพธ์เหมือนกันยกเว้นการทดสอบที่ส่วนใหญ่กระจายไปทั่วทำให้ช้าที่สุด
หากคุณเพิ่มอาร์เรย์ให้มี 1 ล้านรายการสิ่งต่าง ๆ จะเริ่มแตกและคุณจะเหลือวงมาตรฐานเป็นวิธีแก้ปัญหาที่รวดเร็วและreduce
ช้ากว่า
Math.max.apply(Math, arr)
ความเข้ากันได้ 'สูงสุด'
(...)
และapply
อาจล้มเหลวหรือส่งคืนผลลัพธ์ที่ผิดถ้าอาร์เรย์มีองค์ประกอบมากเกินไป [... ] การแก้ปัญหาลดไม่ได้มีปัญหานี้" การทดสอบ Chrome, FF, Edge และ IE11 ดูเหมือนว่ามันเป็น ตกลงสำหรับอาร์เรย์ที่มีค่ามากถึง 100k (ทดสอบบน Win10 และเบราว์เซอร์ล่าสุด: Chrome 110k, Firefox 300k, Edge 400k, IE11 150k)
หากคุณหวาดระแวงเหมือนฉันเกี่ยวกับการใช้Math.max.apply
(ซึ่งอาจทำให้เกิดข้อผิดพลาดเมื่อได้รับอาร์เรย์ขนาดใหญ่ตาม MDN ) ลองสิ่งนี้:
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);
});
}
หรือใน 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));
}
ฟังก์ชั่นที่ไม่ระบุชื่อที่น่าเสียดายที่มีความจำเป็น (แทนการใช้Math.max.bind(Math)
เพราะreduce
ไม่เพียงแค่ผ่านa
และb
ฟังก์ชั่นของมัน แต่ยังi
และมีการอ้างอิงไปยังอาร์เรย์ของตัวเองดังนั้นเราจึงต้องให้แน่ใจว่าเราไม่พยายามที่จะเรียกmax
ในเหล่านั้นเช่นกัน
Math.max(...array)
?
apply
ดังนั้นจึงมีข้อเสียเดียวกัน (ขีด จำกัด อาร์กิวเมนต์สูงสุด)
function arrayMax(array) { return array.reduce(function(a, b) { return Math.max(a, b); }); // <--------- missing ) }
Math.min()
โดยไม่ต้องเรียกค่าใด ๆ ส่งคืนInfinity
ดังนั้นฟังก์ชันเหล่านี้สามารถใช้reduce(..., Infinity)
เพื่อจับคู่พฤติกรรมนั้นได้ ฉันชอบที่จะโยนข้อยกเว้น แต่ (เหมือนที่เป็นอยู่ในปัจจุบัน) เนื่องจากการใช้อาร์เรย์ขั้นต่ำที่ว่างเปล่าน่าจะเป็นข้อผิดพลาด
.apply
มักจะถูกใช้เมื่อความตั้งใจที่จะเรียกใช้ฟังก์ชัน Variadic พร้อมกับรายการค่าอาร์กิวเมนต์เช่น
Math.max([value1[,value2, ...]])
ฟังก์ชันส่งกลับที่ใหญ่ที่สุดของศูนย์หรือมากกว่าตัวเลข
Math.max(10, 20); // 20
Math.max(-10, -20); // -10
Math.max(-10, 20); // 20
Math.max()
วิธีการไม่อนุญาตให้คุณที่จะผ่านในอาร์เรย์ หากคุณมีรายการค่าที่คุณต้องการรับมากที่สุดโดยปกติคุณจะเรียกใช้ฟังก์ชันนี้โดยใช้Function.prototype.apply ()เช่น
Math.max.apply(null, [10, 20]); // 20
Math.max.apply(null, [-10, -20]); // -10
Math.max.apply(null, [-10, 20]); // 20
อย่างไรก็ตามในECMAScript 6คุณสามารถใช้โอเปอเรเตอร์การแพร่กระจาย :
ตัวดำเนินการการแพร่กระจายช่วยให้การแสดงออกที่จะขยายในสถานที่ที่มีข้อโต้แย้งหลาย ๆ (สำหรับการเรียกใช้ฟังก์ชั่น) หรือหลายองค์ประกอบ (สำหรับตัวอักษรอาร์เรย์) คาดว่า
การใช้ตัวดำเนินการสเปรดด้านบนสามารถเขียนใหม่ได้เช่น:
Math.max(...[10, 20]); // 20
Math.max(...[-10, -20]); // -10
Math.max(...[-10, 20]); // 20
เมื่อเรียกใช้ฟังก์ชันโดยใช้โอเปอเรเตอร์ variadic คุณสามารถเพิ่มค่าเพิ่มเติมได้เช่น
Math.max(...[10, 20], 50); // 50
Math.max(...[-10, -20], 50); // 50
โบนัส:
ผู้ประกอบการแพร่กระจายช่วยให้คุณใช้อาร์เรย์ไวยากรณ์ที่แท้จริงในการสร้างอาร์เรย์ใหม่ในสถานการณ์ที่ใน ES5 คุณจะต้องถอยกลับไปยังรหัสความจำเป็นโดยใช้การรวมกันของpush
, splice
ฯลฯ
let foo = ['b', 'c'];
let bar = ['a', ...foo, 'd', 'e']; // ['a', 'b', 'c', 'd', 'e']
concat
โดยโปรแกรมเมอร์ส่วนใหญ่เพราะมันช่วยให้คุณรักษาสไตล์บรรทัดเดียว
สองวิธีที่สั้นกว่าและง่าย:
let arr = [2, 6, 1, 0]
วิธีที่ 1 :
let max = Math.max.apply(null, arr)
วิธีที่ 2 :
let max = arr.reduce(function(a, b) {
return Math.max(a, b);
});
0
คุณสามารถใช้[0].concat(arr)
หรือมีการแพร่กระจายไวยากรณ์[0, ...arr]
(ในสถานที่ของ 'ARR)
คุณทำได้โดยขยายประเภท Array:
Array.max = function( array ){
return Math.max.apply( Math, array );
};
Array.min = function( array ){
return Math.min.apply( Math, array );
};
เพิ่มขึ้นจากที่นี่ (โดย John Resig)
วิธีง่ายๆในการหาค่าต่ำสุดArray
ขององค์ประกอบคือการใช้Array
ฟังก์ชั่นต้นแบบreduce
:
A = [4,3,-9,-2,2,1];
A.reduce((min, val) => val < min ? val : min, A[0]); // returns -9
หรือใช้ฟังก์ชัน Math.Min () ในตัวของ JavaScript (ขอบคุณ @Tenflex):
A.reduce((min,val) => Math.min(min,val), A[0]);
ชุดนี้min
ไปA[0]
และการตรวจสอบแล้วไม่ว่าจะเป็นอย่างเคร่งครัดน้อยกว่าปัจจุบันA[1]...A[n]
min
หากA[i] < min
แล้วมีการปรับปรุงเพื่อmin
A[i]
เมื่อองค์ประกอบอาเรย์ทั้งหมดได้รับการประมวลผลmin
จะถูกส่งคืนเป็นผลลัพธ์
แก้ไข : รวมตำแหน่งของค่าต่ำสุด:
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 }
min
มูลค่าไม่เพียงแต่ส่งกลับ แต่ยังอยู่ในตำแหน่งของมันในอาร์เรย์?
คนอื่น ๆ ได้ให้คำตอบบางอย่างกับพวกเขาArray.prototype
แล้ว ทั้งหมดที่ฉันต้องการในคำตอบนี้คือการชี้แจงว่ามันควรจะเป็นหรือMath.min.apply( Math, array )
ดังนั้นสิ่งที่บริบทควรใช้หรือ?Math.min.apply( null, array )
Math
null
เมื่อผ่านnull
เป็นบริบทไปapply
แล้วบริบทจะเริ่มต้นที่วัตถุทั่วโลก ( window
วัตถุในกรณีของเบราว์เซอร์) ผ่านMath
วัตถุที่เป็นบริบทจะเป็นทางออกที่ถูกต้อง แต่มันจะไม่ทำร้ายผ่านnull
อย่างใดอย่างหนึ่ง นี่คือตัวอย่างเมื่อnull
อาจทำให้เกิดปัญหาเมื่อตกแต่ง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);
ข้างต้นจะโยนข้อยกเว้นเพราะthis.foo
จะได้รับการประเมินว่าเป็นซึ่งเป็นwindow.foo
undefined
หากเราแทนที่null
ด้วยMath
สิ่งต่าง ๆ จะทำงานได้ตามที่คาดหวังและสตริง "foo" จะถูกพิมพ์ไปที่หน้าจอ (ฉันทดสอบโดยใช้Mozilla Rhino )
คุณสามารถสมมติได้ว่าไม่มีใครตกแต่งMath.max
ดังนั้นการส่งผ่านnull
จะทำได้โดยไม่มีปัญหา
Foo.staticMethod
และอ้างอิงthis
? นั่นจะไม่เป็นความผิดพลาดในการออกแบบมัณฑนากรหรือไม่? (เว้นแต่แน่นอนว่าพวกเขาต้องการอ้างอิงขอบเขตทั่วโลกและต้องการรักษาความเป็นอิสระของเครื่องมือ JavaScript ที่ใช้เช่น Rhino)
Math.max
this
หากใครบางคนลบล้างMath.max
สิ่งที่มันใช้this
แล้วพวกเขาได้ทำพฤติกรรมของมันละเมิดข้อมูลจำเพาะและคุณควรโยนวัตถุมีคมที่พวกเขา คุณไม่ควรเขียนรหัสเกี่ยวกับความเป็นไปได้นั้นมากกว่าที่คุณจะเขียนรหัสความเป็นไปได้ที่บางคนเปลี่ยนไปMath.max
และMath.min
สำหรับ lulz
อีกวิธีหนึ่งในการทำ:
var arrayMax = Function.prototype.apply.bind(Math.max, null);
การใช้งาน:
var max = arrayMax([2, 5, 1]);
Math.min
และMath.max
วิธีการดำเนินงานมีทั้ง recursive ที่ถูกเพิ่มเข้าไปในเครื่องยนต์ของ JS โทรกองและส่วนใหญ่ความผิดพลาดสำหรับอาร์เรย์ที่มีจำนวนมากของรายการ
(มากกว่า ~ 10⁷รายการขึ้นอยู่กับเบราว์เซอร์ของผู้ใช้)
Math.max ( ... อาร์เรย์ (1000000) .keys ());
Uncaught RangeError: เกินขนาดสแต็กการโทรสูงสุด
ให้ใช้สิ่งที่ต้องการแทน:
arr.reduce((max, val) => max > val ? max : val, arr[0])
หรือดีกว่าเวลาทำงาน:
function maxValue(arr) {
let max = arr[0];
for (let val of arr) {
if (val > max) {
max = val;
}
}
return max;
}
หรือรับทั้ง Min และ Max:
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] });
}
หรือด้วยเวลาทำงานที่ดียิ่งขึ้น *:
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 };
}
* ทดสอบ 1,000,000 รายการ:
สำหรับการอ้างอิงฟังก์ชั่นที่ 1 รันไทม์ (บนเครื่องของฉัน) คือ 15.84ms เทียบกับฟังก์ชั่นที่ 2 มีเพียง 4.32ms
สิ่งนี้อาจเหมาะสมกับวัตถุประสงค์ของคุณ
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;
}
comparer
ควรจะเรียกว่าอยู่ในขอบเขตที่เฉพาะเจาะจงบางอย่าง? เพราะมันคือการอ้างอิงthis[index]
ซึ่งเป็นundefined
ทุกครั้ง
Math.xxx
) จะทำงานในขอบเขตทั่วโลก ...
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))
สิ่งนี้ใช้ได้สำหรับฉัน
ฉันประหลาดใจที่ไม่มีใครพูดถึงฟังก์ชั่นลด
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]
สำหรับอาร์เรย์ขนาดใหญ่ (องค์ประกอบ ~ 10⁷) Math.min
และMath.max
จัดหา RangeError (เกินขนาดสแต็กการโทรสูงสุด) ใน node.js
สำหรับอาร์เรย์ขนาดใหญ่โซลูชันที่รวดเร็วและสกปรกคือ:
Array.prototype.min = function() {
var r = this[0];
this.forEach(function(v,i,a){if (v<r) r=v;});
return r;
};
ฉันมีปัญหาเดียวกันฉันจำเป็นต้องได้รับค่าต่ำสุดและสูงสุดของอาร์เรย์และเพื่อความประหลาดใจของฉันไม่มีฟังก์ชั่นในตัวสำหรับอาร์เรย์ หลังจากอ่านมากฉันตัดสินใจทดสอบโซลูชัน "top 3" ด้วยตัวเอง:
รหัสการทดสอบคือ:
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;
});
}
อาเรย์ A นั้นเต็มไปด้วยตัวเลขสุ่มจำนวนเต็ม 100,000 ตัวโดยแต่ละฟังก์ชั่นจะถูกประมวลผล 10,000 ครั้งบน Mozilla Firefox 28.0 บนเดสก์ท็อป Intel Pentium 4 2.99GHz พร้อม Windows Vista เวลาอยู่ในหน่วยวินาทีที่ดึงข้อมูลโดย function.now () ฟังก์ชัน ผลการวิจัยพบว่ามีตัวเลข 3 หลักและส่วนเบี่ยงเบนมาตรฐาน:
โซลูชัน REDUCE ช้ากว่าโซลูชันที่ไม่ต่อเนื่อง 117% ทางออกที่แย่กว่านั้นคือ 2,118% ช้ากว่าโซลูชั่นที่ไม่ต่อเนื่อง นอกจากนี้ตามที่ Peter ตั้งข้อสังเกตมันไม่ได้ผลสำหรับอาร์เรย์ขนาดใหญ่ (ประมาณ 1,000,000 องค์ประกอบ)
นอกจากนี้เพื่อทำการทดสอบฉันได้ทดสอบโค้ดที่ไม่ต่อเนื่องนี้แบบขยาย:
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];
}
ระยะเวลา: mean = 0.218s, sd = 0.094
ดังนั้นจึงช้ากว่าโซลูชันที่ไม่ต่อเนื่อง 35% แต่จะดึงทั้งค่าสูงสุดและค่าต่ำสุดในครั้งเดียว (โซลูชันอื่นใดจะใช้เวลาอย่างน้อยสองครั้งเพื่อเรียกคืน) เมื่อ OP ต้องการทั้งสองค่าโซลูชันที่ไม่ต่อเนื่องจะเป็นตัวเลือกที่ดีที่สุด (แม้จะมีฟังก์ชั่นที่แยกกันสองฟังก์ชั่นหนึ่งสำหรับการคำนวณสูงสุดและอีกอันสำหรับการคำนวณขั้นต่ำพวกเขาจะทำได้ดีกว่า
คุณสามารถใช้ฟังก์ชั่นต่อไปนี้ได้ทุกที่ในโครงการของคุณ:
function getMin(array){
return Math.min.apply(Math,array);
}
function getMax(array){
return Math.max.apply(Math,array);
}
จากนั้นคุณสามารถเรียกใช้ฟังก์ชันผ่านอาร์เรย์ได้
var myArray = [1,2,3,4,5,6,7];
var maximo = getMax(myArray); //return the highest number
รหัสต่อไปนี้ใช้งานได้สำหรับฉัน:
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); });
วนซ้ำตามรอยตามที่คุณไป
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 );
สิ่งนี้จะปล่อยให้ min / max null เป็นโมฆะหากไม่มีองค์ประกอบในอาร์เรย์ จะตั้งค่า min และ max ในหนึ่งรอบถ้าอาร์เรย์มีองค์ประกอบใด ๆ
คุณสามารถขยาย Array ด้วยrange
วิธีการที่ใช้ด้านบนเพื่อให้สามารถนำมาใช้ซ้ำและปรับปรุงการอ่านได้ ดูซอที่ใช้งานได้ที่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 }
};
ใช้เป็น
var arr = [3, 9, 22, -7, 44, 18, 7, 9, 15];
var range = arr.range();
console.log(range.min);
console.log(range.max);
range
ฟังก์ชั่นที่จะเป็นวิธีที่ดีที่สุดในการรับทั้งนาทีและสูงสุดในเวลาเดียวกัน IMO - เช่นเดียวกับที่ฉันทำกับการอัพเดตคำตอบของฉัน
ฉันคิดว่าฉันจะแบ่งปันวิธีแก้ปัญหาที่ง่ายและเข้าใจง่าย
สำหรับนาที:
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);
และสำหรับสูงสุด:
var arr = [3, 4, 12, 1, 0, 5];
var max = arr[0];
for (var k = 1; k < arr.length; k++) {
if (arr[k] > max) {
max = arr[k];
}
}
console.log("Max is: " + max);
นอกเหนือจากการใช้ฟังก์ชั่นคณิตศาสตร์ max และ min แล้วฟังก์ชั่นอื่นที่จะใช้ก็คือฟังก์ชั่นการเรียง (): ในตัวเราไปกันเลย
const nums = [12, 67, 58, 30].sort((x, y) =>
x - y)
let max = nums[0]
let min = nums[nums.length -1]
เรื่องง่าย ๆ จริงๆ
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());
นี่เป็นวิธีหนึ่งในการรับค่าสูงสุดจากอาร์เรย์ของวัตถุ สร้างสำเนา (พร้อมชิ้น) จากนั้นเรียงลำดับสำเนาตามลำดับจากมากไปน้อยแล้วหยิบรายการแรก
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;
ใช้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
วิธีการแก้ปัญหาของ ChaosPandion ใช้งานได้หากคุณใช้โพรโทไพ ถ้าไม่พิจารณาสิ่งนี้:
Array.max = function( array ){
return Math.max.apply( Math, array );
};
Array.min = function( array ){
return Math.min.apply( Math, array );
};
ด้านบนจะส่งคืน NaN หากค่าอาร์เรย์ไม่ใช่จำนวนเต็มดังนั้นคุณควรสร้างฟังก์ชันการทำงานบางอย่างเพื่อหลีกเลี่ยงปัญหานั้น มิฉะนั้นจะใช้งานได้
Math
วัตถุเป็นบริบท
หากคุณใช้ไลบรารีsugar.jsคุณสามารถเขียนarr.min ()และarr.max ()ตามที่คุณแนะนำ นอกจากนี้คุณยังสามารถรับค่า min และ max ได้จากอาร์เรย์ที่ไม่ใช่ตัวเลข
min (map, all = false)ส่งคืนองค์ประกอบในอาร์เรย์ด้วยค่าต่ำสุด แผนที่อาจเป็นฟังก์ชั่นการทำแผนที่ค่าที่จะตรวจสอบหรือสตริงที่ทำหน้าที่เป็นทางลัด หากทั้งหมดเป็นจริงจะส่งคืนค่าขั้นต่ำทั้งหมดในอาร์เรย์
max (map, all = false)ส่งคืนองค์ประกอบในอาร์เรย์ด้วยค่าที่มากที่สุด แผนที่อาจเป็นฟังก์ชั่นการทำแผนที่ค่าที่จะตรวจสอบหรือสตริงที่ทำหน้าที่เป็นทางลัด หากเป็นจริงจะส่งคืนค่าสูงสุดทั้งหมดในอาร์เรย์
ตัวอย่าง:
[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 }
let arr = [2,5,3,5,6,7,1];
let max = Math.max(...arr); // 7
let min = Math.min(...arr); // 1
ลอง
let max= a=> a.reduce((m,x)=> m>x ? m:x);
let min= a=> a.reduce((m,x)=> m<x ? m:x);
สำหรับ Math.min / max (+ Apply) เราได้รับข้อผิดพลาด:
เกินจำนวนสแต็กการโทรสูงสุด (Chrome 74.0.3729.131)
...
) ด้วยเช่นนี้Math.max()
Math.max(...[2, 5, 16, 1])
ดูคำตอบของฉันทำจากเอกสาร MDN