จัดเรียงอาร์เรย์ตามชื่อ (ตัวอักษร) ใน Javascript


645

ฉันได้อาร์เรย์ (ดูด้านล่างสำหรับหนึ่งวัตถุในอาร์เรย์) ที่ฉันต้องการเรียงลำดับตามชื่อโดยใช้ JavaScript ฉันจะทำมันได้อย่างไร

var user = {
   bio: null,
   email:  "user@domain.com",
   firstname: "Anna",
   id: 318,
   lastAvatar: null,
   lastMessage: null,
   lastname: "Nickson",
   nickname: "anny"
};

เป็นไปได้ที่ซ้ำกันของอาร์เรย์เรียง JavaScript ของออบเจกต์
Felix Kling

คำตอบ:


1065

usersสมมติว่าคุณมีอาร์เรย์ คุณสามารถใช้users.sortและผ่านฟังก์ชั่นที่ใช้สองข้อโต้แย้งและเปรียบเทียบพวกเขา (comparator)

มันควรจะกลับมา

  • สิ่งที่เป็นลบถ้าอาร์กิวเมนต์แรกมีค่าน้อยกว่าวินาที (ควรอยู่ก่อนอาร์กิวเมนต์ที่สองในอาร์เรย์ที่ได้)
  • สิ่งที่เป็นบวกถ้าอาร์กิวเมนต์แรกมีค่ามากกว่า (ควรอยู่หลังจากอาร์กิวเมนต์ที่สอง)
  • 0 ถ้าองค์ประกอบทั้งสองนั้นเท่ากัน

ในกรณีของเราถ้ามีสององค์ประกอบaและbเราต้องการเปรียบเทียบa.firstnameและb.firstname

ตัวอย่าง:

users.sort(function(a, b){
    if(a.firstname < b.firstname) { return -1; }
    if(a.firstname > b.firstname) { return 1; }
    return 0;
})

รหัสนี้จะทำงานกับทุกประเภท

ทราบว่าใน "ชีวิตจริง" ™คุณมักจะต้องการที่จะไม่สนใจกรณีที่ถูกต้องเรียงลำดับกำกับสัญลักษณ์แปลก ๆ เช่นเอสเอส ฯลฯ localeCompareเมื่อคุณเปรียบเทียบสตริงดังนั้นคุณอาจต้องการที่จะใช้ ดูคำตอบอื่น ๆ เพื่อความชัดเจน


5
Friggin ยอดเยี่ยม ... ฉันกำลังเรียงลำดับนักเขียนบทโดย id ... ทำงานเหมือนมีเสน่ห์ ขอบคุณมาก!
โคดี้

74
สำหรับผู้ที่มาในภายหลังคำตอบของ Mrchief ดีกว่าเพราะมันไม่ตรงตามตัวพิมพ์ใหญ่ - เล็ก
mlienau

25
@mlienau ฉันจะไม่เรียกมันว่าดีขึ้นหรือแย่ลง มันเป็นเพียงอีก
RiaD

19
@RiaD ยุติธรรมเพียงพอ แค่คิดไม่ถึงหลาย ๆ กรณีของการเรียงลำดับรายการตามตัวอักษรรวมถึงตัวเรือนที่ 'Zebra' ปรากฏในรายการก่อน 'apple' จะมีประโยชน์มาก
mlienau

15
รหัสนี้จะใช้ได้กับประเทศที่ใช้ภาษาอังกฤษเท่านั้น ในประเทศอื่น ๆ คุณควรจะใช้คำตอบ ovunccetin localeCompareกับ
Spoike

543

รหัสที่สั้นที่สุดที่เป็นไปได้กับ ES6!

users.sort((a, b) => a.firstname.localeCompare(b.firstname))

String.prototype.localeCompare ()การสนับสนุนขั้นพื้นฐานเป็นสากล!


27
โดยคำตอบที่ดีที่สุดถ้าคุณอาศัยอยู่ในปี 2560
nathanbirrell

52
คำตอบที่ดีที่สุดยังถ้าคุณอาศัยอยู่ในปี 2018;)
Simone

49
อาจเป็นคำตอบที่ดีที่สุดสำหรับ 2019 ด้วย
Ahmad Maleki

23
2563 หรือ naaa
kspearrin

15
อาคนในปี 2030 น้ำท่วมโลกและนี้ทำงานเฉพาะในภูเขา
Starfs

343

บางสิ่งเช่นนี้

array.sort(function(a, b){
 var nameA=a.name.toLowerCase(), nameB=b.name.toLowerCase();
 if (nameA < nameB) //sort string ascending
  return -1;
 if (nameA > nameB)
  return 1;
 return 0; //default return value (no sorting)
});

43
เมื่อเรียงลำดับสตริง 'toLowerCase ()' มีความสำคัญมาก - ตัวอักษรพิมพ์ใหญ่อาจส่งผลต่อการเรียงลำดับของคุณ
MarzSocks

3
ในกรณีที่คนอื่นกำลังสงสัยว่า toLowerCase ส่งผลกระทบอย่างไรมันไม่มาก:'a'>'A' //true 'z'>'a' //true 'A'>'z' //false
SimplGy

14
@SimplGy ฉันขอยืนยันว่าผลกระทบของมันมีมากกว่าที่คุณให้เครดิต ยกตัวอย่างเช่นที่ระบุไว้ในการแสดงความคิดเห็นที่จะเป็นคำตอบที่ได้รับการยอมรับมันเป็นสิ่งสำคัญที่จะรู้หรือไม่ว่าฟังก์ชั่นการจัดเรียงของคุณจะเรียงลำดับสตริง'Zebra'สูงกว่าสตริงซึ่งมันจะทำอย่างไรถ้าคุณไม่ได้ใช้'apple' .toLowerCase()
PrinceTyke

1
@ PrinceTyke ใช่นั่นเป็นกรณีที่ดี 'Z' < 'a' // trueและ'z' < 'a' // false
SimplGy

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

336

หากสตริงเปรียบเทียบมีอักขระยูนิโค้ดคุณสามารถใช้localeCompareฟังก์ชันของStringคลาสดังนี้:

users.sort(function(a,b){
    return a.firstname.localeCompare(b.firstname);
})

3
String.localeCompare ไม่รองรับ Safari และ IE <11 :)
CORSAIR

13
@CARAIR มันได้รับการสนับสนุนเป็นเพียงพารามิเตอร์ที่สองและสามที่ไม่ได้รับการสนับสนุน
Codler

6
@CORSAIR การใช้งานในตัวอย่างได้รับการสนับสนุนในเบราว์เซอร์ IE ที่สำคัญทั้งหมด: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... LocaleCompare ยังคำนึงถึงการใช้อักษรตัวพิมพ์ใหญ่ด้วยดังนั้นฉันคิดว่าการติดตั้งนี้ควรได้รับการพิจารณาว่าเป็นแนวปฏิบัติที่ดีที่สุด
Matt Jensen

9
users.sort ((a, b) => a.firstname.localeCompare (b.firstname)) // สั้น ๆ เวอร์ชั่น ES6 หวาน!
Nachiketha

4
ถังขยะ ในการใช้ ES6users.sort((a, b) => a.name.localeCompare(b.name))
Mohmmad Ebrahimi การรับอาวัล

32

Nice เล็กน้อย ES6 หนึ่งซับ:

users.sort((a, b) => a.firstname !== b.firstname ? a.firstname < b.firstname ? -1 : 1 : 0);

2
อันนี้ไม่สมบูรณ์เพราะมันไม่ได้จัดการค่าที่เท่ากันอย่างถูกต้อง
Karl-Johan Sjögren

1
แน่นอนว่าฉันต้องเพิ่มการตรวจสอบค่าที่ตรงกัน
Sam Logan

ไม่เลวฉันเดาว่าถ้าคุณต้องการมันทั้งหมดในหนึ่งบรรทัด ternaries ซ้อนกันได้สับสนสำหรับการอ่านแม้ว่า
22419

24

เราสามารถใช้ localeCompare แต่จำเป็นต้องตรวจสอบกุญแจเช่นกันสำหรับค่าความผิดพลาด

รหัสด้านล่างจะไม่ทำงานหากรายการหนึ่งไม่มี lname

obj.sort((a, b) => a.lname.localeCompare(b.lname))

ดังนั้นเราต้องตรวจสอบค่าความผิดพลาดดังด้านล่าง

let obj=[
{name:'john',lname:'doe',address:'Alaska'},
{name:'tom',lname:'hopes',address:'California'},
{name:'harry',address:'Texas'}
]
let field='lname';
console.log(obj.sort((a, b) => (a[field] || "").toString().localeCompare((b[field] || "").toString())));

หรือ

เราสามารถใช้ lodash มันง่ายมาก มันจะตรวจจับค่าที่ส่งคืนเช่นไม่ว่าจะเป็นตัวเลขหรือสตริงและทำการเรียงลำดับตาม

import sortBy from 'lodash/sortBy';
sortBy(obj,'name')

https://lodash.com/docs/4.17.5#sortBy


2
Lodash ค่อนข้างเรียบร้อย! ไม่เคยได้ยินมาก่อน ใช้งานได้ดี!
Derk Jan Speelman

15

underscorejsเสนอฟังก์ชั่น _.sortBy ที่ดีมาก:

_.sortBy([{a:1},{a:3},{a:2}], "a")

หรือคุณสามารถใช้ฟังก์ชั่นการเรียงลำดับแบบกำหนดเอง:

_.sortBy([{a:"b"},{a:"c"},{a:"a"}], function(i) {return i.a.toLowerCase()})

2
ตัวอย่างที่สองเกี่ยวข้องกับการส่งคืนสตริง ไม่sortByตรวจสอบค่าส่งกลับเป็นสตริงและจึงทำการเรียงลำดับตามตัวอักษร? ขอบคุณ
superjos

12

ในกรณีที่เรามีการเรียงลำดับชื่อหรือสิ่งที่มีตัวอักษรพิเศษเช่นñหรือAEIOU (คอมมอนส์ในภาษาสเปน) เราสามารถใช้ params สถานที่ ( ESสำหรับสเปนในกรณีนี้) และตัวเลือกเช่นนี้

let user = [{'firstname': 'Az'},{'firstname': 'Áb'},{'firstname':'ay'},{'firstname': 'Ña'},{'firstname': 'Nz'},{'firstname': 'ny'}];


user.sort((a, b) => a.firstname.localeCompare(b.firstname, 'es', {sensitivity: 'base'}))


console.log(user)

ตัวเลือกสถานที่แบบเป็นทางการสามารถพบได้ที่นี่ในiana , es (สเปน), de (เยอรมัน), fr (ฝรั่งเศส) เกี่ยวกับความไว ฐานหมายถึง:

เฉพาะสตริงที่แตกต่างในตัวอักษรฐานเปรียบเทียบเป็นไม่เท่ากัน ตัวอย่าง: a ≠ b, a = á, a = A


8

โดยทั่วไปคุณสามารถจัดเรียงอาร์เรย์ด้วยวิธีการเรียงลำดับ แต่ถ้าคุณต้องการเรียงลำดับวัตถุคุณต้องผ่านฟังก์ชั่นในการเรียงลำดับวิธีการเรียงลำดับดังนั้นฉันจะให้ตัวอย่างโดยใช้อาร์เรย์ของคุณ

user = [{
bio: "<null>",
email: "user@domain.com",
firstname: 'Anna',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "user@domain.com",
firstname: 'Senad',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
},
{
bio: "<null>",
email: "user@domain.com",
firstname: 'Muhamed',
id: 318,
"last_avatar": "<null>",
"last_message": "<null>",
lastname: 'Nickson',
nickname: 'anny'
}];

var ar = user.sort(function(a, b)
{
  var nA = a.firstname.toLowerCase();
  var nB = b.firstname.toLowerCase();

  if(nA < nB)
    return -1;
  else if(nA > nB)
    return 1;
 return 0;
});

ทำไมส่งคืน 0 เมื่อสิ้นสุด
โนบิตะ

=, เมื่อสตริงเหมือนกัน
Senad Meškin

แต่ในกรณีนั้นไม่ควรelseถูกลบ? มิฉะนั้นreturn 0จะไม่มีใครอ่าน
โนบิตะ

2
นั่นไม่ใช่ "อื่น ๆ " เป็น "อย่างอื่นถ้า"
Senad Meškin


8

สัญกรณ์กระชับมากขึ้น:

user.sort(function(a, b){
    return a.firstname === b.firstname ? 0 : a.firstname < b.firstname ? -1 : 1;
})

มีขนาดกะทัดรัดกว่า แต่ละเมิดสัญญา: sign(f(a, b)) =-sign(f(b, a))(สำหรับ a = b)
RiaD

3
a.firstname == b.firstnameควรกลับมาใช้===เพื่อความสมบูรณ์
puiu

6

ทั้ง asec และ desc sort คุณสามารถใช้สิ่งนี้ได้: สมมติว่าเรามีตัวแปรSortTypeที่ระบุการเรียงจากน้อยไปมากหรือจากมากไปหาน้อยที่คุณต้องการ:

 users.sort(function(a,b){
            return   sortType==="asc"? a.firstName.localeCompare( b.firstName): -( a.firstName.localeCompare(  b.firstName));
        })

5

ฟังก์ชั่นทั่วไปสามารถเขียนได้ดังนี้

    function getSortedData(data, prop, isAsc) {
        return data.sort((a, b) => (a[prop] < b[prop] ? -1 : 1) * (isAsc ? 1 : -1));
   }

คุณสามารถผ่านพารามิเตอร์ด้านล่าง

  1. ข้อมูลที่คุณต้องการเรียงลำดับ
  2. คุณสมบัติในข้อมูลโดยมันควรจะเรียงลำดับ
  3. พารามิเตอร์สุดท้ายเป็นประเภทบูลีน ตรวจสอบว่าคุณต้องการเรียงลำดับจากน้อยไปหามากหรือจากมากไปน้อย

4

ลอง

users.sort((a,b)=> (a.firstname>b.firstname)*2-1)


2
ฟังก์ชั่นการเรียงลำดับควรกลับ -1,0,1 อันนี้คืนค่า -1,1 เท่านั้น
Radu Luncasu

@RaduLuncasu - คุณสามารถให้ข้อมูลการทดสอบ (อาร์เรย์ผู้ใช้) ซึ่งแสดงให้เห็นว่าวิธีการแก้ปัญหาข้างต้นให้ผลที่ไม่ถูกต้อง? (เท่าที่ฉันรู้ไม่มีศูนย์ไม่มีปัญหา)
Kamil Kiełczewski

ถ้า CompareFunction (a, b) ส่งคืนค่า 0 ปล่อยให้ a และ b ไม่เปลี่ยนแปลงตามความเคารพซึ่งกันและกัน แต่เรียงลำดับตามองค์ประกอบที่แตกต่างกันทั้งหมด
Radu Luncasu


@RaduLuncasu โอเค แต่ข้อมูลนั้นไม่ได้หมายความว่าจะต้องมีค่าเป็นศูนย์ วิธีที่ดีที่สุดในการแสดงคือเตรียมข้อมูลที่ไม่ได้ผล แต่เท่าที่ฉันรู้ว่ามันเป็นไปไม่ได้ - เช่น[9,8,7,6,5,1,2,3].sort((a,b) => a<b ? -1 : 1)
Kamil Kiełczewski

3

คุณสามารถใช้สิ่งนี้กับวัตถุ

transform(array: any[], field: string): any[] {
return array.sort((a, b) => a[field].toLowerCase() !== b[field].toLowerCase() ? a[field].toLowerCase() < b[field].toLowerCase() ? -1 : 1 : 0);}

2

ในคำง่ายๆคุณสามารถใช้วิธีนี้

users.sort(function(a,b){return a.firstname < b.firstname ? -1 : 1});

1

คุณสามารถใช้วิธีการอาร์เรย์ในตัว sort- วิธีนี้ใช้วิธีการโทรกลับเป็นพารามิเตอร์



    // custom sort function to be passed as param/callback to the Array's sort method
    function myCustomSort(a, b) {
        return (a.toLowerCase() > b.toLowerCase()) ? 1 : -1;
    }

    // Actual method to be called by entity that needs sorting feature
    function sortStrings() {
        var op = Array.prototype.sort.call(arguments, myCustomSort);
    }

    // Testing the implementation
    var sortedArray = sortStrings("Burger", "Mayo1", "Pizza", "boxes", "Apples", "Mayo");
    console.log(sortedArray); //["Apples", "boxes", "Burger", "Mayo", "Mayo1", "Pizza"]


ประเด็นสำคัญที่ควรสังเกตสำหรับการทำความเข้าใจรหัสนี้

  1. วิธีการที่กำหนดเองในกรณีนี้ myCustomSortควรส่งกลับค่า +1 หรือ -1 สำหรับการเปรียบเทียบแต่ละองค์ประกอบคู่ (จากอาร์เรย์อินพุต)
  2. ใช้toLowerCase()/ toUpperCase()ในวิธีการจัดเรียงการโทรกลับแบบกำหนดเองเพื่อให้ความแตกต่างของกรณีไม่ส่งผลกระทบต่อความถูกต้องของกระบวนการจัดเรียง

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

ไชโย!


ไม่ใช่คำตอบที่เหมาะสมเพราะจะทำการตรวจสอบน้อยกว่าและมากกว่าและไม่ใช่การตรวจสอบที่เท่ากัน
Steel Brain

มันยังไม่นำสิ่งใหม่ ๆ มาสู่โต๊ะเทียบกับคำตอบใด ๆ ที่นั่งอยู่ที่นั่นตั้งแต่ปี 2011
amenthes

1

ใส่คำตอบที่ดีที่สุดลงในต้นแบบเพื่อเรียงลำดับตามคีย์

Array.prototype.alphaSortByKey= function (key) {
    this.sort(function (a, b) {
        if (a[key] < b[key])
            return -1;
        if (a[key] > b[key])
            return 1;
        return 0;
    });
    return this;
};

0

คุณสามารถใช้สิ่งที่คล้ายกันเพื่อกำจัดตัวพิมพ์เล็กและตัวพิมพ์ใหญ่

users.sort(function(a, b){

  //compare two values
  if(a.firstname.toLowerCase() < b.firstname.toLowerCase()) return -1;
  if(a.firstname.toLowerCase() > b.firstname.toLowerCase()) return 1;
  return 0;

})

7
คำตอบเดียวกับ Mrchief ด้วยข้อเสียเพิ่มเติมที่ toLowerCase จะทำสี่ครั้งต่อการเปรียบเทียบแทนสองครั้ง
amenthes

0

การใช้งานของฉันทำงานได้ดีในเวอร์ชัน ES ที่เก่ากว่า:

sortObject = function(data) {
    var keys = Object.keys(data);
    var result = {};

    keys.sort();

    for(var i = 0; i < keys.length; i++) {
        var key = keys[i];

        result[key] = data[key];
    }

    return result;
};

0

สำหรับเร็กคอร์ดถ้าคุณต้องการให้มีการเรียงลำดับชื่อฟังก์ชั่นไวยากรณ์จะเป็นดังนี้:

let sortFunction = (a, b) => {
 if(a.firstname < b.firstname) { return -1; }
 if(a.firstname > b.firstname) { return 1; }
 return 0;
})
users.sort(sortFunction)

โปรดทราบว่าสิ่งต่อไปนี้ใช้ไม่ได้:

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