Sắp xếp mảng theo tên (theo bảng chữ cái) trong Javascript


646

Tôi có một mảng (xem bên dưới cho một đối tượng trong mảng) mà tôi cần sắp xếp theo tên đầu tiên bằng JavaScript. Tôi làm nó như thế nào?

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

Câu trả lời:


1067

Giả sử bạn có một mảng users. Bạn có thể sử dụng users.sortvà truyền một hàm có hai đối số và so sánh chúng (bộ so sánh)

Nó sẽ trở lại

  • một cái gì đó tiêu cực nếu đối số thứ nhất nhỏ hơn giây (nên được đặt trước đối số thứ hai trong mảng kết quả)
  • một cái gì đó tích cực nếu đối số thứ nhất lớn hơn (nên được đặt sau cái thứ hai)
  • 0 nếu hai phần tử đó bằng nhau.

Trong trường hợp của chúng tôi nếu hai yếu tố là abchúng tôi muốn so sánh a.firstnameb.firstname

Thí dụ:

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

Mã này sẽ làm việc với bất kỳ loại.

Lưu ý rằng trong "đời thực" ™, bạn thường muốn bỏ qua trường hợp, sắp xếp chính xác các dấu phụ, các ký hiệu lạ như ß, v.v. khi bạn so sánh các chuỗi, vì vậy bạn có thể muốn sử dụng localeCompare. Xem câu trả lời khác cho rõ ràng.


5
Friggin tuyệt vời ... Tôi đang sắp xếp một nhân vật học theo id ... hoạt động như một cơ duyên. Thx một tấn!
Cody

74
Đối với những người đến vào một ngày sau đó, câu trả lời của Mrchief là tốt hơn bởi vì nó không nhạy cảm.
mlienau

25
@mlienau, tôi sẽ không gọi nó là tốt hơn hay tệ hơn. Nó chỉ là một thứ khác
Rịa

19
@RiaD đủ công bằng. Không thể nghĩ ra nhiều trường hợp sắp xếp các mục theo thứ tự bảng chữ cái bao gồm cả vỏ, trong đó 'Zebra' xuất hiện trong danh sách trước 'apple', sẽ rất hữu ích.
mlienau

15
Mã này sẽ chỉ hoạt động trên các quốc gia nói tiếng Anh. Ở các quốc gia khác, bạn nên sử dụng câu trả lời của ovunccetin vớilocaleCompare .
Spoike

545

Mã ngắn nhất có thể với ES6!

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

Hỗ trợ cơ bản String.prototype.localeCompare () là phổ quát!


27
Cho đến nay câu trả lời tốt nhất nếu bạn đang sống trong năm 2017
nathanbirrell

52
Câu trả lời hay nhất nếu bạn sống trong năm 2018;)
Simone

49
Có lẽ sẽ là câu trả lời tốt nhất cho năm 2019.
Ahmad Maleki

23
2020 có thể? hay naaa?
kspearrin

15
Người đàn ông, vào năm 2030, lũ lụt và điều này chỉ hoạt động ở vùng núi.
Starfs

343

Một cái gì đó như thế này:

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
Khi sắp xếp chuỗi 'toLowerCase ()' là rất quan trọng - chữ in hoa có thể ảnh hưởng đến sắp xếp của bạn.
MarzSocks

3
Trong trường hợp bất kỳ ai khác đang tự hỏi những gì toLowerCase tác động, thì nó không nhiều:'a'>'A' //true 'z'>'a' //true 'A'>'z' //false
SimplGy

14
@SimplGy Tôi cho rằng tác động của nó nhiều hơn một chút so với việc bạn cho nó tín dụng. Ví dụ, như đã nêu trong các nhận xét cho câu trả lời được chấp nhận, điều quan trọng là phải biết liệu hàm sắp xếp của bạn có sắp xếp chuỗi 'Zebra'cao hơn chuỗi hay không 'apple', điều này sẽ làm nếu bạn không sử dụng .toLowerCase().
PrinceTyke 04/08/2015

1
@PrinceTyke yeah đó là một người đàn ông tốt. 'Z' < 'a' // true'z' < 'a' // false
SimplGy

2
Tất cả các điểm hợp lệ và tôi muốn nói sắp xếp luôn là một loại "nó phụ thuộc". Nếu bạn sắp xếp theo tên, độ nhạy trường hợp có thể không quan trọng. Trong các trường hợp khác, nó có thể. Bất kể, tôi nghĩ rằng việc áp dụng vào tình huống cụ thể của một người không khó một khi bạn có được ý tưởng cốt lõi.
Ông trùm

336

Nếu các chuỗi được so sánh chứa các ký tự unicode, bạn có thể sử dụng localeComparechức năng của Stringlớp như sau:

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

3
String.localeCompare không hỗ trợ Safari và IE <11 :)
CORSAIR

13
@CORSAIR nó được hỗ trợ, nó chỉ là tham số thứ hai và thứ ba không được hỗ trợ.
Codler

6
@CORSAIR việc sử dụng trong ví dụ này được hỗ trợ trong tất cả các trình duyệt IE chính: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ . LocaleCompare cũng tính đến vốn hóa, vì vậy tôi nghĩ việc triển khai này nên được coi là thực tiễn tốt nhất.
Matt Jensen

9
users.sort ((a, b) => a.firstname.localeCompare (b.firstname)) // Phiên bản ES6 ngắn n ngọt ngào!
Nachiketha

4
xe tăng bro. sử dụng ES6users.sort((a, b) => a.name.localeCompare(b.name))
Mohmmad Ebrahimi Aval

32

ES6 nhỏ xinh một lót:

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

2
Cái này không đầy đủ vì nó không xử lý đúng các giá trị bằng nhau.
Karl-Johan Sjögren

1
Tất nhiên, cảm ơn vì đã phát hiện ra điều đó, tôi đã thêm một kiểm tra cho các giá trị khớp
Sam Logan

không tệ, tôi đoán rằng nếu bạn thực sự muốn tất cả trên một dòng, các chú chim nhạn lồng nhau sẽ gây nhầm lẫn cho khả năng đọc
russter

24

Chúng tôi có thể sử dụng localeCompare nhưng cũng cần kiểm tra các khóa cũng cho các giá trị falsey

Mã dưới đây sẽ không hoạt động nếu một mục bị thiếu tên.

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

Vì vậy, chúng ta cần kiểm tra giá trị falsey như dưới đây

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())));

HOẶC LÀ

chúng ta có thể sử dụng lodash, nó rất đơn giản. Nó sẽ phát hiện các giá trị được trả về tức là số hay chuỗi và thực hiện sắp xếp phù hợp.

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

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


2
Nhà nghỉ là khá gọn gàng! Chưa từng nghe về nó trước đây. Hoạt động tuyệt vời!
Derk Jan Speelman

15

underscorejs Mời các chức năng _.sortBy rất đẹp:

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

hoặc bạn có thể sử dụng chức năng sắp xếp tùy chỉnh:

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

2
ví dụ thứ hai liên quan đến các chuỗi trả về. Có sortByphát hiện các giá trị được trả về là các chuỗi và do đó thực hiện sắp xếp theo thứ tự chữ cái không? Cảm ơn
superjos

12

Trong trường hợp chúng tôi đang sắp xếp tên hoặc một cái gì đó có các ký tự đặc biệt, như ñ hoặc áéíóú (commons trong tiếng Tây Ban Nha), chúng tôi có thể sử dụng các ngôn ngữ params ( es cho tiếng Tây Ban Nha trong trường hợp này) và các tùy chọn như sau:

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)

Các tùy chọn địa phương chính thức có thể được tìm thấy ở đây trong iana , es (tiếng Tây Ban Nha), de (tiếng Đức), fr (tiếng Pháp). Về cơ sở độ nhạy có nghĩa là:

Chỉ các chuỗi khác nhau trong các chữ cái cơ sở so sánh là không bằng nhau. Ví dụ: a ≠ b, a = á, a = A.


8

Về cơ bản bạn có thể sắp xếp các mảng với sắp xếp phương thức, nhưng nếu bạn muốn sắp xếp các đối tượng thì bạn phải truyền hàm để sắp xếp phương thức của mảng, vì vậy tôi sẽ cho bạn một ví dụ sử dụng mảng của bạn

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;
});

Tại sao trả về 0 ở cuối?
Nobita

=, khi các chuỗi giống nhau
Senad Meškin

Nhưng trong trường hợp đó không nên elseloại bỏ? Nếu không thì điều đó return 0sẽ không bao giờ được đọc
Nobita

2
đó không phải là "khác", đó là "khác nếu"
Senad Meškin


8

Một ký hiệu nhỏ gọn hơn:

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

nó nhỏ gọn hơn nhưng vi phạm hợp đồng của nó: sign(f(a, b)) =-sign(f(b, a))(cho a = b)
Rịa

3
trở lại a.firstname == b.firstnamenên sử dụng ===cho đầy đủ
puiu

6

Ngoài ra, đối với cả sắp xếp asec và desc, bạn có thể sử dụng điều này: giả sử chúng ta có một SortType biến xác định sắp xếp tăng dần hoặc sắp xếp giảm dần mà bạn muốn:

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

5

Một hàm tổng quát có thể được viết như dưới đây

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

bạn có thể vượt qua các tham số dưới đây

  1. Dữ liệu bạn muốn sắp xếp
  2. Các thuộc tính trong dữ liệu nên được sắp xếp
  3. Tham số cuối cùng là loại boolean. Nó kiểm tra xem bạn muốn sắp xếp theo tăng dần hay giảm dần

4

thử

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


2
hàm sắp xếp sẽ trả về -1,0,1. cái này chỉ trả về -1,1.
Radu Luncasu

@RaduLuncasu - bạn có thể cung cấp dữ liệu thử nghiệm (mảng người dùng) cho thấy giải pháp trên cho kết quả sai không? (theo tôi biết, thiếu số 0 không có vấn đề gì)
Kamil Kiełczewski

Nếu so sánh hàm (a, b) trả về 0, không thay đổi a và b đối với nhau, nhưng được sắp xếp theo tất cả các yếu tố khác nhau.
Radu Luncasu


@RaduLuncasu ok, nhưng thông tin đó không có nghĩa là không bắt buộc. Cách tốt nhất để hiển thị nó là chuẩn bị dữ liệu không hoạt động - nhưng theo tôi biết thì điều này là không thể - ví dụ[9,8,7,6,5,1,2,3].sort((a,b) => a<b ? -1 : 1)
Kamil Kiełczewski

3

Bạn có thể sử dụng điều này cho các đối tượng

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

nói một cách đơn giản bạn có thể sử dụng phương pháp này

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

1

Bạn có thể sử dụng phương thức mảng dựng sẵn - sort. Phương thức này lấy phương thức gọi lại làm tham số



    // 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"]


Những điểm chính cần lưu ý để hiểu mã này.

  1. Trong trường hợp này, phương thức tùy chỉnh myCustomSortsẽ trả về +1 hoặc -1 cho mỗi cặp phần tử (từ mảng đầu vào).
  2. Sử dụng toLowerCase()/ toUpperCase()trong phương thức gọi lại sắp xếp tùy chỉnh để trường hợp khác biệt không ảnh hưởng đến tính chính xác của quy trình sắp xếp.

Tôi hy vọng điều này là đủ giải thích rõ ràng. Hãy bình luận nếu bạn nghĩ rằng, cần thêm thông tin.

Chúc mừng!


Không phải là một câu trả lời thích hợp bởi vì nó chỉ thực hiện ít hơn và lớn hơn kiểm tra và không phải là kiểm tra bằng nhau.
Bộ não thép

nó cũng không mang lại điều gì mới mẻ trên bàn, so với bất kỳ câu trả lời nào đã được ngồi ở đó kể từ ~ 2011.
amenthes

1

Đẩy các câu trả lời hàng đầu vào một nguyên mẫu để sắp xếp theo khóa.

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

Bạn có thể sử dụng một cái gì đó tương tự, để thoát khỏi trường hợp nhạy cảm

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
Câu trả lời tương tự như câu trả lời của Mrchief. Với nhược điểm hơn nữa là toLowerCase được thực hiện bốn lần mỗi lần so sánh thay vì hai lần.
amenthes

0

Triển khai của tôi, hoạt động rất tốt trong các phiên bản ES cũ hơn:

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

Chỉ dành cho bản ghi, nếu bạn muốn có một hàm sắp xếp có tên, cú pháp như sau:

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

Lưu ý rằng những điều sau KHÔNG hoạt động:

users.sort(sortFunction(a,b))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.