ฉันมีชุดของสตริงที่ฉันต้องการเรียงลำดับในจาวาสคริปต์ แต่ในกรณีที่ไม่คำนึงถึงขนาดตัวพิมพ์ วิธีการทำสิ่งนี้?
ฉันมีชุดของสตริงที่ฉันต้องการเรียงลำดับในจาวาสคริปต์ แต่ในกรณีที่ไม่คำนึงถึงขนาดตัวพิมพ์ วิธีการทำสิ่งนี้?
คำตอบ:
ใน (เกือบ :) หนึ่งซับ
["Foo", "bar"].sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
ซึ่งส่งผลให้
[ 'bar', 'Foo' ]
ในขณะที่
["Foo", "bar"].sort();
ผลลัพธ์ใน
[ 'Foo', 'bar' ]
return a.localeCompare(b, 'en', {'sensitivity': 'base'});
toLowerCase()
เมื่อlocaleCompare
ทำได้โดยค่าเริ่มต้นในบางกรณี คุณสามารถอ่านเพิ่มเติมเกี่ยวกับพารามิเตอร์ที่จะส่งผ่านได้ที่นี่: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
myArray.sort(
function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
}
);
แก้ไข: โปรดทราบว่าฉันเดิมเขียนสิ่งนี้เพื่อแสดงเทคนิคแทนที่จะมีประสิทธิภาพในใจ โปรดอ้างอิงคำตอบ @Ivan Krechetov สำหรับโซลูชันที่กะทัดรัดยิ่งขึ้น
toLowerCase
สองครั้งในแต่ละสตริง จะมีประสิทธิภาพมากกว่าในการจัดเก็บสตริงที่ลดลงในตัวแปร
.toLowerCase()
หลายครั้งสำหรับแต่ละรายการในอาร์เรย์ ตัวอย่างเช่น 45 การเรียกไปยังฟังก์ชันการเปรียบเทียบเมื่อเรียงลำดับ 10 รายการในลำดับย้อนกลับ var i = 0; ["z","y","x","w","v","u","t","s","r","q"].sort(function (a, b) {++i; return a.toLowerCase().localeCompare(b.toLowerCase());}); console.log("Calls to Compare: " + i); // i === 45
ถึงเวลาทบทวนคำถามเก่านี้อีกครั้ง
toLowerCase
คุณไม่ควรใช้โซลูชั่นอาศัย พวกเขาไม่มีประสิทธิภาพและไม่สามารถใช้งานได้ในบางภาษา (เช่นภาษาตุรกี) ชอบสิ่งนี้:
['Foo', 'bar'].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))
ตรวจสอบเอกสารเกี่ยวกับความเข้ากันได้ของเบราว์เซอร์และสิ่งที่ต้องรู้เกี่ยวกับsensitivity
ตัวเลือก
arr.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
if (a == b) return 0;
if (a > b) return 1;
return -1;
});
return a === b ? 0 : a > b ? 1 : -1;
["111", "33"]
เราอาจต้องการให้มันกลับมา["111", "33"]
เพราะ 1 มาก่อน 3 ในการสั่งรหัสตัวอักษร แต่ฟังก์ชั่นในคำตอบนี้จะกลับมา["33", "111"]
เพราะจำนวนน้อยกว่าจำนวน33
111
"33" > "111" === true
33 > 111 === false
มันทำงานได้ตามที่ตั้งใจไว้
นอกจากนี้คุณยังสามารถใช้Intl.Collator().compare
MDN ใหม่ได้อย่างมีประสิทธิภาพเมื่อเรียงลำดับอาร์เรย์ ข้อเสียคือเบราว์เซอร์รุ่นเก่าไม่รองรับ MDN ระบุว่าไม่รองรับเลยใน Safari จำเป็นต้องตรวจสอบเนื่องจากระบุว่าIntl.Collator
รองรับ
เมื่อเปรียบเทียบสตริงจำนวนมากเช่นในการจัดเรียงอาร์เรย์ขนาดใหญ่จะเป็นการดีกว่าที่จะสร้างออบเจกต์ Intl.Collator และใช้ฟังก์ชันที่มีให้โดยคุณสมบัติการเปรียบเทียบ
["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"]
หากคุณต้องการรับประกันคำสั่งเดียวกันโดยไม่คำนึงถึงลำดับขององค์ประกอบในอาร์เรย์อินพุตนี่คือการเรียงลำดับที่เสถียร :
myArray.sort(function(a, b) {
/* Storing case insensitive comparison */
var comparison = a.toLowerCase().localeCompare(b.toLowerCase());
/* If strings are equal in case insensitive comparison */
if (comparison === 0) {
/* Return case sensitive comparison instead */
return a.localeCompare(b);
}
/* Otherwise return result */
return comparison;
});
ปกติในกรณีที่มี.sort()
.toLowerCase()
คุณยังสามารถใช้ตัวดำเนินการ Elvis:
arr = ['Bob', 'charley', 'fudge', 'Fudge', 'biscuit'];
arr.sort(function(s1, s2){
var l=s1.toLowerCase(), m=s2.toLowerCase();
return l===m?0:l>m?1:-1;
});
console.log(arr);
ให้:
biscuit,Bob,charley,fudge,Fudge
วิธี localeCompare น่าจะดีแม้ว่า ...
หมายเหตุ: ตัวดำเนินการ Elvis เป็นรูปแบบสั้น ๆ ว่า 'ผู้ประกอบการที่ประกอบไปด้วยสามส่วน' หากเป็นเช่นนั้นโดยทั่วไปจะมีการมอบหมาย
หากคุณมองไปที่?: ด้านข้างดูเหมือนว่า Elvis ...
เช่นแทนที่จะเป็น:
if (y) {
x = 1;
} else {
x = 2;
}
คุณสามารถใช้ได้:
x = y?1:2;
เช่นเมื่อ y เป็นจริงแล้วส่งคืน 1 (สำหรับการมอบหมายให้ x) มิฉะนั้นคืน 2 (สำหรับการมอบหมายให้ x)
x = y ? y : z
x = y ?: z
Javascript ไม่มีโอเปอเรเตอร์ Elvis จริงๆ แต่คุณสามารถใช้x = y || z
ในลักษณะเดียวกันได้
คำตอบอื่น ๆ สมมติว่าอาร์เรย์มีสตริง วิธีการของฉันจะดีกว่าเพราะมันจะทำงานแม้ว่าอาร์เรย์มีโมฆะไม่ได้กำหนดหรืออื่น ๆ ที่ไม่ใช่สตริง
var notdefined;
var myarray = ['a', 'c', null, notdefined, 'nulk', 'BYE', 'nulm'];
myarray.sort(ignoreCase);
alert(JSON.stringify(myarray)); // show the result
function ignoreCase(a,b) {
return (''+a).toUpperCase() < (''+b).toUpperCase() ? -1 : 1;
}
null
จะถูกจัดเรียงระหว่าง nulk 'และ 'nulm' แต่undefined
จะได้รับการเสมอเรียงสุดท้าย
(''+notdefined) === "undefined"
มันจะเรียงลำดับก่อน "z"
Array.prototype.sort
: | เพราะส่วนที่เกี่ยวกับ(''+notdefined) === "undefined"
เป็นจริง ... ซึ่งหมายความว่าถ้าคุณพลิก -1 และ 1 ในฟังก์ชั่นการเรียงลำดับเพื่อกลับคำสั่งซื้อที่ไม่ได้กำหนดยังคงเรียงลำดับไปยังจุดสิ้นสุด นอกจากนี้ยังจำเป็นต้องได้รับการพิจารณาเมื่อใช้ฟังก์ชันการเปรียบเทียบนอกบริบทของการเรียงลำดับอาร์เรย์ (เช่นเดียวกับเมื่อฉันมาถึงคำถามนี้)
Array.prototype.sort
นิยามนั้น- เพิ่มความคิดเห็นให้มากขึ้น ก่อนอื่นไม่จำเป็นต้องใช้(''+a)
- ECMAScript toString()
จะต้องเรียกใช้องค์ประกอบก่อนที่จะส่งไปยัง comparFn ประการที่สองความจริงที่ว่าignoreCase
ผลตอบแทน1
เมื่อเปรียบเทียบสตริงที่เท่ากัน (รวมเท่ากัน แต่สำหรับกรณี) หมายความว่าข้อมูลจำเพาะไม่ได้กำหนดผลลัพธ์หากมีค่าที่ซ้ำกัน
undefined
เป็นกรณีพิเศษซึ่งสำหรับใด ๆ x x <ไม่ได้กำหนดและ x> ไม่ได้กำหนดมีทั้งที่เป็นเท็จ นั่นundefined
เป็นครั้งสุดท้ายเสมอเป็นผลพลอยได้จากการดำเนินการเรียงลำดับของการเรียงลำดับ ฉันพยายามเปลี่ยน ('' + a) เป็นเพียง a แต่มันล้มเหลว TypeError: a.toUpperCase is not a function
ฉันจะได้รับ เห็นได้ชัดว่าไม่ได้toString
ถูกเรียกก่อนการเปรียบเทียบ comparFn
undefined
การเปรียบเทียบไม่เคยเรียกว่า
รุ่น ES6:
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
เพื่อรองรับคำตอบที่ยอมรับฉันต้องการเพิ่มว่าฟังก์ชั่นด้านล่างดูเหมือนจะเปลี่ยนค่าในอาเรย์ดั้งเดิมที่จะเรียงลำดับเพื่อไม่เพียง แต่จะเรียงลำดับตัวพิมพ์เล็ก แต่ค่าบนจะเปลี่ยนเป็นตัวพิมพ์เล็กด้วย นี่เป็นปัญหาสำหรับฉันเพราะแม้ว่าฉันต้องการเห็นแมรี่ข้างแมรี่ แต่ฉันไม่ต้องการให้กรณีของค่าแรกที่แมรี่เปลี่ยนเป็นตัวพิมพ์เล็ก
myArray.sort(
function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
}
);
ในการทดลองของฉันฟังก์ชันต่อไปนี้จากคำตอบที่ยอมรับจะเรียงลำดับอย่างถูกต้อง แต่ไม่เปลี่ยนค่า
["Foo", "bar"].sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
สิ่งนี้อาจช่วยได้หากคุณพยายามเข้าใจ:
var array = ["sort", "Me", "alphabetically", "But", "Ignore", "case"];
console.log('Unordered array ---', array, '------------');
array.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
console.log("Compare '" + a + "' and '" + b + "'");
if( a == b) {
console.log('Comparison result, 0 --- leave as is ');
return 0;
}
if( a > b) {
console.log('Comparison result, 1 --- move '+b+' to before '+a+' ');
return 1;
}
console.log('Comparison result, -1 --- move '+a+' to before '+b+' ');
return -1;
});
console.log('Ordered array ---', array, '------------');
// return logic
/***
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
***/
arr.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
if( a == b) return 0;
if( a > b) return 1;
return -1;
});
ในฟังก์ชั่นด้านบนถ้าเราเปรียบเทียบเมื่อตัวพิมพ์เล็กสองค่า a และ b เราจะไม่ได้ผลลัพธ์ที่ดี
ตัวอย่างถ้าอาร์เรย์เป็น [A, a, B, c, C, C, D, e, E] และเราใช้ฟังก์ชันข้างต้นเรามีอาร์เรย์นั้น มันไม่เปลี่ยนแปลงอะไรเลย
การมีผลลัพธ์คือ [A, a, B, C, c, D, d, E, e] เราควรเปรียบเทียบอีกครั้งเมื่อค่าตัวพิมพ์เล็กสองตัวเท่ากัน:
function caseInsensitiveComparator(valueA, valueB) {
var valueALowerCase = valueA.toLowerCase();
var valueBLowerCase = valueB.toLowerCase();
if (valueALowerCase < valueBLowerCase) {
return -1;
} else if (valueALowerCase > valueBLowerCase) {
return 1;
} else { //valueALowerCase === valueBLowerCase
if (valueA < valueB) {
return -1;
} else if (valueA > valueB) {
return 1;
} else {
return 0;
}
}
}
ฉันหุ้มคำตอบที่ดีที่สุดไว้ในโพลีฟิลล์เพื่อที่ฉันจะสามารถเรียก. sortIgnoreCase () บนอาเรย์สตริง
// Array.sortIgnoreCase() polyfill
if (!Array.prototype.sortIgnoreCase) {
Array.prototype.sortIgnoreCase = function () {
return this.sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
};
}
/ /i
ตัดสายของคุณใน นี่เป็นวิธีที่ง่ายในการใช้ regex เพื่อละเว้นการใส่ปลอก