Sắp xếp đối tượng JavaScript theo khóa


532

Tôi cần sắp xếp các đối tượng JavaScript theo khóa.

Do đó như sau:

{ 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }

Sẽ trở thành:

{ 'a' : 'dsfdsfsdf', 'b' : 'asdsad', 'c' : 'masdas' }


39
Trở lại năm 2011 (khi câu hỏi này được đăng), thông số ECMAScript nói rằng các đối tượng JavaScript không có thứ tự vốn có - thứ tự quan sát được phụ thuộc vào việc triển khai và do đó không thể dựa vào. Tuy nhiên, hóa ra tất cả các công cụ JavaScript được triển khai ít nhiều cùng một ngữ nghĩa, vì vậy những công cụ này hiện đã được chuẩn hóa trong ES6 . Kết quả là, rất nhiều câu trả lời dưới đây được sử dụng là chính xác theo thông số kỹ thuật, nhưng bây giờ không chính xác.
Mathias Bynens

Nói ngắn gọn, hãy sử dụng chuỗi được sắp xếp khi bạn cần so sánh hoặc băm kết quả: npmjs.com/package/json-urdy-opesify
exebook

Cho rằng các đối tượng chỉ là bản đồ, hoặc ký hiệu tùy thuộc vào ngôn ngữ của bạn, có rất ít lý do tại sao bạn sẽ làm điều này. RATNG SAU, Nói chung, thứ tự mà chúng được đưa vào bản đồ trên thực tế là thứ tự chúng cư trú khi xâu chuỗi. VÌ VẬY, nếu bạn đã tạo một bản đồ mới và các giá trị được chỉ định dựa trên danh sách khóa được định sẵn, bạn sẽ tìm cho mình một bản đồ được sắp xếp dựa trên các khóa
Fallenreaper

Lưu ý rằng kể từ khi Object.entriesObject.fromEntriesđược thêm vào JS, điều này có thể đạt được với một lớp lót ngắn độc đáo:Object.fromEntries(Object.entries(obj).sort())
Mike 'Pomax' Kamermans

Câu trả lời:


471

Các câu trả lời khác cho câu hỏi này đã lỗi thời, không bao giờ phù hợp với thực tế triển khai và đã chính thức trở thành không chính xác khi thông số ES6 / ES2015 đã được xuất bản.


Xem phần về thứ tự lặp lại thuộc tính trong Khám phá ES6 của Axel Rauschmayer :

Tất cả các phương thức lặp trên các khóa thuộc tính đều thực hiện theo cùng một thứ tự:

  1. Đầu tiên tất cả các chỉ số Array, được sắp xếp bằng số.
  2. Sau đó, tất cả các khóa chuỗi (không phải là chỉ mục), theo thứ tự mà chúng được tạo.
  3. Sau đó, tất cả các biểu tượng, theo thứ tự mà chúng được tạo ra.

Vì vậy, có, các đối tượng JavaScript trong thực tế ra lệnh, và thứ tự của các phím của họ / tài sản có thể được thay đổi.

Đây là cách bạn có thể sắp xếp một đối tượng theo các khóa / thuộc tính của nó, theo thứ tự abc:

const unordered = {
  'b': 'foo',
  'c': 'bar',
  'a': 'baz'
};

console.log(JSON.stringify(unordered));
// → '{"b":"foo","c":"bar","a":"baz"}'

const ordered = {};
Object.keys(unordered).sort().forEach(function(key) {
  ordered[key] = unordered[key];
});

console.log(JSON.stringify(ordered));
// → '{"a":"baz","b":"foo","c":"bar"}'

Sử dụng varthay vì consttương thích với các công cụ ES5.


5
Tôi thực sự không thể thấy sự khác biệt đối với mã của bạn và câu trả lời hàng đầu ở đây ngoài việc sử dụng một kỹ thuật lặp hơi khác. Việc các đối tượng có thể được cho là "ra lệnh" hay không dường như không liên quan. Câu trả lời cho câu hỏi này vẫn giống nhau. Các thông số kỹ thuật được công bố chỉ xác nhận các câu trả lời ở đây.
Phil

6
FYI, đã được làm rõ rằng thứ tự liệt kê của các tài sản vẫn chưa được xác định: esdiscuss.org/topic/ mẹo
Felix Kling

6
@ Phil_1984_ Câu trả lời này và câu trả lời được bình chọn hàng đầu rất khác nhau. Câu hỏi của OP là làm thế nào để sắp xếp một đối tượng theo nghĩa đen. Câu trả lời được bình chọn hàng đầu nói rằng bạn không thể, sau đó đưa ra cách giải quyết bằng cách lưu trữ các khóa được sắp xếp trong một mảng, sau đó lặp lại và in các cặp giá trị khóa từ mảng đã sắp xếp. Câu trả lời này tuyên bố rằng thứ tự của các đối tượng bằng chữ hiện có thể sắp xếp được và ví dụ của anh ta lưu các giá trị khóa được sắp xếp trở lại thành một đối tượng bằng chữ, sau đó in trực tiếp đối tượng đã sắp xếp. Mặt khác, sẽ rất tuyệt nếu trang web được liên kết vẫn tồn tại.
cchamberlain 14/03/2016

6
Cả hai câu trả lời chỉ đơn giản là sử dụng hàm Array.sort để sắp xếp các khóa trước. OP đang yêu cầu sắp xếp một "đối tượng JavaScript" và chỉ sử dụng Ký hiệu đối tượng JavaScript (JSON) để mô tả 2 đối tượng. 2 đối tượng này có ý nghĩa sắp xếp giống hệt nhau về mặt logic là không liên quan. Tôi nghĩ rằng câu trả lời hàng đầu giải thích điều này tốt hơn rất nhiều. Nói "tất cả các câu trả lời khác bây giờ chính thức không chính xác" là quá cực đối với tôi, đặc biệt là với một liên kết bị hỏng. Tôi nghĩ vấn đề là "thông số ES6 mới này" đang tạo ảo giác rằng các đối tượng Javascript có một danh sách các khóa được sắp xếp không đúng.
Phil

1
Vui lòng thêm rằng giải pháp này không được hỗ trợ bởi nhiều trình duyệt hiện đại (google "caniuse ES6"). Sử dụng câu trả lời này có nguy cơ lỗi khó tìm trong một số trình duyệt nhất định (ví dụ: Safari khi Chrome hoàn toàn ổn).
Manuel Arwed Schmidt

244

Các đối tượng JavaScript 1 không được đặt hàng. Thật vô nghĩa khi cố gắng "sắp xếp" chúng. Nếu bạn muốn lặp lại các thuộc tính của đối tượng, bạn có thể sắp xếp các khóa và sau đó truy xuất các giá trị liên quan:

var myObj = {
    'b': 'asdsadfd',
    'c': 'masdasaf',
    'a': 'dsfdsfsdf'
  },
  keys = [],
  k, i, len;

for (k in myObj) {
  if (myObj.hasOwnProperty(k)) {
    keys.push(k);
  }
}

keys.sort();

len = keys.length;

for (i = 0; i < len; i++) {
  k = keys[i];
  console.log(k + ':' + myObj[k]);
}


Thực hiện thay thế bằng cách sử dụng Object.keysfanciness:

var myObj = {
    'b': 'asdsadfd',
    'c': 'masdasaf',
    'a': 'dsfdsfsdf'
  },
  keys = Object.keys(myObj),
  i, len = keys.length;

keys.sort();

for (i = 0; i < len; i++) {
  k = keys[i];
  console.log(k + ':' + myObj[k]);
}


1 Không phải là mô phạm, nhưng không có đối tượng JSON .


2
@MarcelKorpel Có một đối tượng JSON. Kiểm tra phần 8 của RFC JSON chính thức: ietf.org/rfc/rfc4627.txt
Paul

8
@Paulpro hai điều cần lưu ý về RFC đó: đầu tiên, nó 7 tuổi vào thời điểm này và từ vựng thay đổi theo thời gian; thứ hai, "Bản ghi nhớ này cung cấp thông tin cho cộng đồng Internet. Nó không chỉ định tiêu chuẩn Internet dưới bất kỳ hình thức nào." Việc một chuỗi ký tự cho trước đại diện cho một đối tượng JavaScript bằng chữ hay văn bản JSON tùy thuộc vào ngữ cảnh / cách sử dụng. Thuật ngữ "đối tượng JSON" xáo trộn và làm cho sự khác biệt trở nên mơ hồ theo một cách bất lợi. Hãy loại bỏ thuật ngữ không chính xác và sử dụng thuật ngữ chính xác hơn nếu có thể. Tôi thấy không có lý do để làm khác. Từ ngữ quan trọng.
Matt Ball

6
@MattBall IMO JSON Object là một thuật ngữ rất chính xác cho một chuỗi giống {"a", 1}như JSON Array là thuật ngữ chính xác cho một chuỗi như [1]. Thật hữu ích khi có thể giao tiếp bằng cách nói những thứ như đối tượng thứ ba trong mảng của tôi khi bạn có chuỗi [{x: 1}, {y: 2}, {z: 3}], vì vậy tôi rất thích "Đó không phải là một đối tượng JSON" khi bình luận về một chữ Javascript, thay vào đó "Không có như vậy điều như một đối tượng JSON ", điều này sẽ gây ra nhiều nhầm lẫn và khó khăn hơn trong giao tiếp sau này khi OP thực sự đang làm việc với JSON.
Paul

3
@Paulpro Tôi phải không đồng ý. {"a", 1}là một đối tượng theo nghĩa đen hoặc văn bản JSON (còn gọi là chuỗi JSON, nếu bạn thực sự thích). Cái nào phụ thuộc vào ngữ cảnh, cái trước nếu nó xuất hiện nguyên văn trong mã nguồn JavaScript, cái sau nếu đó là một chuỗi cần được chuyển đến bộ phân tích cú pháp JSON để sử dụng thêm. Có sự khác biệt thực sự giữa hai khi nói đến cú pháp được phép, cách sử dụng chính xác và tuần tự hóa.
Matt Ball

4
Bây giờ ES6 / ES2015 đã được hoàn thành, câu trả lời này đã chính thức trở thành không chính xác. Xem câu trả lời của tôi để biết thêm.
Mathias Bynens

172

Rất nhiều người đã đề cập rằng "các đối tượng không thể được sắp xếp" , nhưng sau đó họ sẽ đưa ra cho bạn một giải pháp hiệu quả. Nghịch lý, phải không?

Không ai đề cập đến lý do tại sao những giải pháp đó đang làm việc. Chúng là bởi vì trong hầu hết các giá trị triển khai của trình duyệt trong các đối tượng được lưu trữ theo thứ tự chúng được thêm vào. Đó là lý do tại sao nếu bạn tạo đối tượng mới từ danh sách khóa được sắp xếp, nó sẽ trả về kết quả mong đợi.

Và tôi nghĩ rằng chúng ta có thể thêm một giải pháp nữa - cách chức năng ES5:

function sortObject(obj) {
    return Object.keys(obj).sort().reduce(function (result, key) {
        result[key] = obj[key];
        return result;
    }, {});
}

Phiên bản ES2015 ở trên (được định dạng thành "một lớp"):

const sortObject = o => Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})

Giải thích ngắn về các ví dụ trên (như đã hỏi trong các bình luận):

Object.keysđang cung cấp cho chúng tôi danh sách các khóa trong đối tượng được cung cấp ( objhoặc o), sau đó chúng tôi sắp xếp chúng bằng thuật toán sắp xếp mặc định, tiếp theo .reduceđược sử dụng để chuyển mảng đó trở lại thành đối tượng, nhưng lần này với tất cả các khóa được sắp xếp.


7
@Pointy Hành vi này luôn có sẵn trong tất cả các trình duyệt chính và đã được chuẩn hóa trong ES6 / ES2015 . Tôi muốn nói rằng đây là lời khuyên tốt.
Mathias Bynens

3
Đây là cách đơn giản nhất và ngắn gọn nhất để hoàn thành nhiệm vụ trong EcmaScript v5. Một chút muộn cho bữa tiệc nhưng nên là câu trả lời được chấp nhận.
Steven de Salas

2
"Chúng là bởi vì trong hầu hết các giá trị triển khai của trình duyệt trong các đối tượng được lưu trữ theo thứ tự chúng được thêm vào" Chỉ dành cho các thuộc tính không phải là số. Cũng lưu ý rằng vẫn không có gì đảm bảo thứ tự các thuộc tính được lặp lại (ví dụ thông qua for...in).
Felix Kling

2
Rất vui được giải thích lý do tại sao nó hoạt động, nó đã làm bài học cho tôi. Cảm ơn!
ola

5
Người nói dối của tôi đã phàn nàn về điều đó (trả lại một bài tập), nhưng bài này làm việc cho tôi và dễ đọc hơn:Object.keys(dict).sort().reduce((r, k) => Object.assign(r, { [k]: dict[k] }), {});
aks.

68

Tôi đang bị sốc theo nghĩa bóng! Chắc chắn tất cả các câu trả lời là hơi cũ, nhưng thậm chí không ai đề cập đến sự ổn định trong sắp xếp! Vì vậy, hãy kiên nhẫn với tôi, tôi sẽ cố gắng hết sức để trả lời câu hỏi và đi vào chi tiết ở đây. Vì vậy, tôi sẽ xin lỗi bây giờ nó sẽ rất nhiều để đọc.

Vì là năm 2018 nên tôi sẽ chỉ sử dụng ES6, các Polyfills đều có sẵn tại các tài liệu MDN, mà tôi sẽ liên kết ở phần đã cho.


Trả lời câu hỏi:

Nếu các khóa của bạn chỉ là số thì bạn có thể sử dụng an toàn Object.keys()cùng với Array.prototype.reduce()để trả về đối tượng đã sắp xếp:

// Only numbers to show it will be sorted.
const testObj = {
  '2000': 'Articel1',
  '4000': 'Articel2',
  '1000': 'Articel3',
  '3000': 'Articel4',
};

// I'll explain what reduces does after the answer.
console.log(Object.keys(testObj).reduce((accumulator, currentValue) => {
  accumulator[currentValue] = testObj[currentValue];
  return accumulator;
}, {}));

/**
 * expected output:
 * {
 * '1000': 'Articel3',
 * '2000': 'Articel1',
 * '3000': 'Articel4',
 * '4000': 'Articel2' 
 *  } 
 */

// if needed here is the one liner:
console.log(Object.keys(testObj).reduce((a, c) => (a[c] = testObj[c], a), {}));

Tuy nhiên, nếu bạn đang làm việc với các chuỗi, tôi khuyên bạn nên kết nối Array.prototype.sort()tất cả những điều này:

// String example
const testObj = {
  'a1d78eg8fdg387fg38': 'Articel1',
  'z12989dh89h31d9h39': 'Articel2',
  'f1203391dhj32189h2': 'Articel3',
  'b10939hd83f9032003': 'Articel4',
};
// Chained sort into all of this.
console.log(Object.keys(testObj).sort().reduce((accumulator, currentValue) => {
  accumulator[currentValue] = testObj[currentValue];
  return accumulator;
}, {}));

/**
 * expected output:   
 * { 
 * a1d78eg8fdg387fg38: 'Articel1',
 * b10939hd83f9032003: 'Articel4',
 * f1203391dhj32189h2: 'Articel3',
 * z12989dh89h31d9h39: 'Articel2' 
 * }
 */

// again the one liner:
console.log(Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}));

Nếu ai đó đang tự hỏi những gì giảm làm:

// Will return Keys of object as an array (sorted if only numbers or single strings like a,b,c).
Object.keys(testObj)

// Chaining reduce to the returned array from Object.keys().
// Array.prototype.reduce() takes one callback 
// (and another param look at the last line) and passes 4 arguments to it: 
// accumulator, currentValue, currentIndex and array
.reduce((accumulator, currentValue) => {

  // setting the accumulator (sorted new object) with the actual property from old (unsorted) object.
  accumulator[currentValue] = testObj[currentValue];

  // returning the newly sorted object for the next element in array.
  return accumulator;

  // the empty object {} ist the initial value for  Array.prototype.reduce().
}, {});

Nếu cần ở đây là lời giải thích cho một lớp lót:

Object.keys(testObj).reduce(

  // Arrow function as callback parameter.
  (a, c) => 

  // parenthesis return! so we can safe the return and write only (..., a);
  (a[c] = testObj[c], a)

  // initial value for reduce.
  ,{}
);

Tại sao Sắp xếp hơi phức tạp:

Tóm Object.keys()lại sẽ trả về một mảng có cùng thứ tự như chúng ta nhận được với một vòng lặp bình thường:

const object1 = {
  a: 'somestring',
  b: 42,
  c: false
};

console.log(Object.keys(object1));
// expected output: Array ["a", "b", "c"]

Object.keys () trả về một mảng có các phần tử là các chuỗi tương ứng với các thuộc tính có thể đếm được tìm thấy trực tiếp trên đối tượng. Thứ tự của các thuộc tính giống như thứ tự được đưa ra bằng cách lặp qua các thuộc tính của đối tượng theo cách thủ công.

Sidenote - bạn cũng có thể sử dụng Object.keys()trên các mảng, hãy nhớ rằng chỉ mục sẽ được trả về:

// simple array
const arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

Nhưng nó không dễ dàng như trong các ví dụ đó, các đối tượng trong thế giới thực có thể chứa các số và ký tự chữ cái hoặc thậm chí các ký hiệu (xin đừng làm như vậy).

Dưới đây là một ví dụ với tất cả chúng trong một đối tượng:

// This is just to show what happens, please don't use symbols in keys.
const testObj = {
  '1asc': '4444',
  1000: 'a',
  b: '1231',
  '#01010101010': 'asd',
  2: 'c'
};

console.log(Object.keys(testObj));
// output: [ '2', '1000', '1asc', 'b', '#01010101010' ]

Bây giờ nếu chúng ta sử dụng Array.prototype.sort()trên mảng phía trên đầu ra thay đổi:

console.log(Object.keys(testObj).sort());
// output: [ '#01010101010', '1000', '1asc', '2', 'b' ]

Đây là một trích dẫn từ các tài liệu:

Phương thức sort () sắp xếp các phần tử của một mảng tại chỗ và trả về mảng. Các loại không nhất thiết phải ổn định. Thứ tự sắp xếp mặc định là theo các điểm mã Unicode chuỗi.

Sự phức tạp về thời gian và không gian của loại không thể được đảm bảo vì nó phụ thuộc vào việc thực hiện.

Bạn phải chắc chắn rằng một trong số chúng trả về đầu ra mong muốn cho bạn. Trong các ví dụ thực tế, mọi người có xu hướng trộn lẫn mọi thứ, đặc biệt nếu bạn sử dụng các thông tin đầu vào khác nhau như API và Cơ sở dữ liệu với nhau.


Vậy thỏa thuận lớn nào?

Vâng, có hai bài viết mà mọi lập trình viên nên hiểu:

Thuật toán tại chỗ :

Trong khoa học máy tính, thuật toán tại chỗ là một thuật toán biến đổi đầu vào không sử dụng cấu trúc dữ liệu phụ trợ. Tuy nhiên, một lượng nhỏ không gian lưu trữ bổ sung được phép cho các biến phụ trợ. Đầu vào thường được ghi đè bởi đầu ra khi thuật toán thực thi. Thuật toán tại chỗ cập nhật trình tự đầu vào chỉ thông qua thay thế hoặc hoán đổi các phần tử. Một thuật toán không tại chỗ đôi khi được gọi là không đúng chỗ hoặc không đúng chỗ.

Vì vậy, về cơ bản mảng cũ của chúng tôi sẽ được ghi đè! Điều này rất quan trọng nếu bạn muốn giữ mảng cũ vì những lý do khác. Vì vậy, hãy ghi nhớ điều này.

Thuật toán sắp xếp

Các thuật toán sắp xếp ổn định sắp xếp các phần tử giống hệt nhau theo cùng thứ tự xuất hiện trong đầu vào. Khi sắp xếp một số loại dữ liệu, chỉ một phần dữ liệu được kiểm tra khi xác định thứ tự sắp xếp. Ví dụ, trong ví dụ sắp xếp thẻ ở bên phải, các thẻ đang được sắp xếp theo thứ hạng của chúng và bộ đồ của chúng bị bỏ qua. Điều này cho phép khả năng nhiều phiên bản được sắp xếp chính xác khác nhau của danh sách gốc. Các thuật toán sắp xếp ổn định chọn một trong số các thuật toán này, theo quy tắc sau: nếu hai mục so sánh bằng nhau, như hai thẻ 5, thì thứ tự tương đối của chúng sẽ được giữ nguyên, do đó, nếu một cái đi trước cái kia trong đầu vào, nó cũng sẽ đến trước cái khác trong đầu ra.

nhập mô tả hình ảnh ở đây

Một ví dụ về loại ổn định trên thẻ chơi. Khi các thẻ được sắp xếp theo thứ hạng với sắp xếp ổn định, hai 5s phải giữ nguyên thứ tự trong đầu ra được sắp xếp mà chúng ban đầu. Khi chúng được sắp xếp với một loại không ổn định, 5s có ​​thể kết thúc ngược lại thứ tự trong đầu ra được sắp xếp.

Điều này cho thấy việc sắp xếp là đúng nhưng nó đã thay đổi. Vì vậy, trong thế giới thực ngay cả khi việc sắp xếp là chính xác, chúng ta phải đảm bảo rằng chúng ta có được những gì chúng ta mong đợi! Đây là siêu quan trọng giữ điều này trong tâm trí là tốt. Để biết thêm các ví dụ JavaScript, hãy xem Array.prototype.sort () - docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort


3
Bạn flippin rock, cảm ơn bạn cho câu trả lời đáng kinh ngạc này. Một trong những điều tốt nhất tôi từng thấy trên SO. Chúc mừng.
Gavin

Nếu chỉ bạn có thể cung cấp một phương pháp kỳ dị để sử dụng vào cuối. Câu trả lời tuyệt vời mặc dù!
mmm

@momomo vấn đề là, tùy thuộc vào những gì bạn mong đợi từ việc sắp xếp, không có phương pháp đúng. Tuy nhiên, bạn chỉ có thể sử dụng đoạn mã này từ câu trả lời của tôi : Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}).
Megajin

Không ổn định loại không áp dụng cho câu hỏi này: chúng tôi đang sắp xếp theo khóa đối tượng và khóa là duy nhất. (Để mở rộng ví dụ về thẻ của bạn: không bao giờ có thể có hai 5s trong gói, ngay cả khi chúng là những bộ đồ khác nhau.)
Darren Cook

@DarrenCook câu hỏi hay! Bạn đúng sẽ không bao giờ có cùng khóa trong một đối tượng. Tuy nhiên, sự ổn định phức tạp hơn chỉ là tính duy nhất của một phím. Hầu hết thời gian một mảng được bao gồm trong sắp xếp các đối tượng. Và đó là khi mọi thứ có thể trở nên không ổn định. Hãy tưởng tượng một trò chơi bài với 5 người chơi. Mỗi tay được đại diện bởi một mảng (để giữ một tay sắp xếp riêng) và các thẻ dưới dạng đối tượng. Nếu thẻ của bạn trông như thế này {5: 'hearts'}hoặc {5: 'spades'}và bạn bắt đầu sắp xếp mảng, nó sẽ trở nên không ổn định trong các trò chơi như rummy. Không nói các ngôn ngữ khác nhau.
Megajin

29

Điều này làm việc cho tôi

/**
 * Return an Object sorted by it's Key
 */
var sortObjectByKey = function(obj){
    var keys = [];
    var sorted_obj = {};

    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            keys.push(key);
        }
    }

    // sort keys
    keys.sort();

    // create new array based on Sorted Keys
    jQuery.each(keys, function(i, key){
        sorted_obj[key] = obj[key];
    });

    return sorted_obj;
};

10
Đây thực sự là câu trả lời chính xác cho câu hỏi trong tầm tay. Để biết phiên bản đơn giản hóa bằng Underscore, hãy xem: jsfiddle.net/wPjaQ/1
radicand

6
@radicand Không có câu trả lời này là không chính xác. Nó trả về một đối tượng mới, cũng không có thứ tự.
Paul

3
@radicand Nó cũng không trong thực tế. Không có thứ gọi là thứ tự trên các khóa đối tượng, vậy làm thế nào bạn có thể nói rằng trong thực tế điều này mang lại cho bạn một đối tượng theo thứ tự được sắp xếp? Nó thực sự chỉ mang lại cho bạn một bản sao nông của đối tượng bạn đi qua.
Paul

9
Điều này là siêu sai. Nó có thể xảy ra để làm việc ngay bây giờ, nhưng sẽ phá vỡ trong một trình duyệt web khác hoặc tải trang khác nhau trong cùng một trình duyệt. Các trình duyệt có thể chọn ngẫu nhiên các khóa đối tượng để bảo mật hoặc khi bạn điền vào một đối tượng, nó sẽ đặt các giá trị vào các thùng bộ nhớ khác nhau tùy thuộc vào các khóa sẽ trả về một thứ tự khác. Nếu điều này xảy ra để làm việc, đó chỉ là may mắn cho bạn.
Yobert

11
Nó cũng có nhu cầu sử dụng jQuery.
Cướp

25

Đó là năm 2019 và chúng tôi có một cách 2019 để giải quyết điều này :)

Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())

2
Làm thế nào để chúng ta sắp xếp các đối tượng lồng nhau theo khóa?
a2441918

@ a2441918 Theo cách tương tự như bạn sẽ làm với hàm sort (). Hãy xem: developer.mozilla.org/de/docs/Web/JavaScript/Reference/ tựa Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). Sort ((k, j ) => k - j))
dùng2912903

Đối với người dùng TypeScript, điều này chưa có sẵn cho chúng tôi, hãy xem: github.com/microsoft/TypeScript/issues/30933
tsujp

Đẹp một lớp lót, nhưng làm thế nào để sắp xếp các phím theo cách không phân biệt chữ hoa chữ thường?
theMaxx

1
@theMaxx Sử dụng một hàm tùy chỉnh để sắp xếp, đại loại như: `` `Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). sort (([key1, val1], [key2, val2]) => key1.toLowerCase (). localeCompare (key2.toLowerCase ()))) ``
Ben

22

đây là 1 lót

var data = { zIndex:99,
             name:'sravan',
             age:25, 
             position:'architect',
             amount:'100k',
             manager:'mammu' };

console.log(Object.entries(data).sort().reduce( (o,[k,v]) => (o[k]=v,o), {} ));


Cú pháp điên này là cái quái gì vậy? (o[k] = v, o). Tại sao điều này thậm chí hoạt động, tôi có thể tìm tài liệu về nó ở đâu? Nó rõ ràng trả về tham số ngoài cùng bên phải, nhưng tại sao?
ntaso

1
@ntaso đây
James

chức năng ngắn trước tiên làm cho o[k]bằng vvà sau đó trả vềo
Tahsin Turkoz

19

Đây là một câu hỏi cũ, nhưng lấy gợi ý từ câu trả lời của Mathias Bynens, tôi đã tạo một phiên bản ngắn để sắp xếp đối tượng hiện tại mà không cần nhiều chi phí.

    Object.keys(unordered).sort().forEach(function(key) {
        var value = unordered[key];
        delete unordered[key];
        unordered[key] = value;
    });

sau khi thực thi mã, chính đối tượng "không có thứ tự" sẽ có các khóa được sắp xếp theo thứ tự abc.


17

Sử dụng lodash này sẽ hoạt động:

some_map = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' }

// perform a function in order of ascending key
_(some_map).keys().sort().each(function (key) {
  var value = some_map[key];
  // do something
});

// or alternatively to build a sorted list
sorted_list = _(some_map).keys().sort().map(function (key) {
  var value = some_map[key];
  // return something that shall become an item in the sorted list
}).value();

Chỉ là thức ăn cho suy nghĩ.


15

Giả sử nó có thể hữu ích trong trình gỡ lỗi VisualStudio hiển thị các thuộc tính đối tượng không có thứ tự.

(function(s){var t={};Object.keys(s).sort().forEach(function(k){t[k]=s[k]});return t})({b:2,a:1,c:3})

Thật tuyệt vời Cảm ơn một sự lỏng lẻo
Mugiwara

Đẹp! Cảm ơn bạn cho giải pháp ngắn gọn này.
Con Antonakos

9

Phiên bản gạch dưới :

function order(unordered)
{
return _.object(_.sortBy(_.pairs(unordered),function(o){return o[0]}));
}

Nếu bạn không tin tưởng trình duyệt của mình để giữ thứ tự các khóa, tôi thực sự khuyên bạn nên dựa vào một mảng được sắp xếp của các mảng được ghép nối theo giá trị khóa.

_.sortBy(_.pairs(c),function(o){return o[0]})

Tốt hơn:_.object(_.sortBy(_.pairs(unordered), _.first))
Afanasii Kurakin

8
function sortObjectKeys(obj){
    return Object.keys(obj).sort().reduce((acc,key)=>{
        acc[key]=obj[key];
        return acc;
    },{});
}

sortObjectKeys({
    telephone: '069911234124',
    name: 'Lola',
    access: true,
});

Có lẽ thêm một số giải thích về mã của bạn là tốt hơn.
aristotll

1
Lấy các khóa của đối tượng, vì vậy nó là mảng các chuỗi, tôi sắp xếp () chúng và vì đó là mảng các chuỗi (khóa) tôi giảm chúng (với less () của js Array). Acc ban đầu là một đối tượng trống {} (đối số cuối cùng của bộ giảm tốc) và bộ giảm tốc (gọi lại) gán cho đối tượng trống các giá trị của nguồn obj với chuỗi khóa được sắp xếp.
dùng3286817

8

Có thể một hình thức thanh lịch hơn một chút:

 /**
     * Sorts a key-value object by key, maintaining key to data correlations.
     * @param {Object} src  key-value object
     * @returns {Object}
     */
var ksort = function ( src ) {
      var keys = Object.keys( src ),
          target = {};
      keys.sort();
      keys.forEach(function ( key ) {
        target[ key ] = src[ key ];
      });
      return target;
    };


// Usage
console.log(ksort({
  a:1,
  c:3,
  b:2  
}));

PS và tương tự với cú pháp ES6 +:

function ksort( src ) {
  const keys = Object.keys( src );
  keys.sort();
  return keys.reduce(( target, key ) => {
        target[ key ] = src[ key ];
        return target;
  }, {});
};

nó chẳng là gì cả bạn vẫn trả lại một đối tượng. bạn không thể bảo đảm các đối tượng trong mục tiêu của bạn thực sự sẽ có bất kỳ trật tự nào. bạn cần trả về một mảng jeeezus.
mmm

điều duy nhất bạn đang làm ở đây là đảm bảo nó là một bộ, theo cách không tối ưu.
mmm

7

sắp xếp đệ quy, cho đối tượng lồng nhau và mảng

function sortObjectKeys(obj){
    return Object.keys(obj).sort().reduce((acc,key)=>{
        if (Array.isArray(obj[key])){
            acc[key]=obj[key].map(sortObjectKeys);
        }
        if (typeof obj[key] === 'object'){
            acc[key]=sortObjectKeys(obj[key]);
        }
        else{
            acc[key]=obj[key];
        }
        return acc;
    },{});
}

// test it
sortObjectKeys({
    telephone: '069911234124',
    name: 'Lola',
    access: true,
    cars: [
        {name: 'Family', brand: 'Volvo', cc:1600},
        {
            name: 'City', brand: 'VW', cc:1200, 
            interior: {
                wheel: 'plastic',
                radio: 'blaupunkt'
            }
        },
        {
            cc:2600, name: 'Killer', brand: 'Plymouth',
            interior: {
                wheel: 'wooden',
                radio: 'earache!'
            }
        },
    ]
});

Tôi nghĩ rằng bạn cần một cái elsetrong đó - có thể đúng cho cả Array.isArray(obj[key])và chotypeof obj[key] === 'object'
jononomo

Khi bạn có một mảng các nguyên hàm, hàm của bạn sẽ biến đổi các nguyên hàm (chuỗi / số) thành các đối tượng trống. Để nắm bắt điều này, tôi đã thêm quyền sau vào đầu hàm của bạn function sortObjectKeys(obj){:: if(typeof obj != 'object'){ /* it is a primitive: number/string (in an array) */ return obj; }. Đối với sự mạnh mẽ, tôi bắt đầu hoàn thành cũng được thêm vào:if(obj == null || obj == undefined){ return obj; }
diễn ra vào

4

Như đã đề cập, các đối tượng là không có thứ tự.

Tuy nhiên...

Bạn có thể thấy thành ngữ này hữu ích:

var o = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' };

var kv = [];

for (var k in o) {
  kv.push([k, o[k]]);
}

kv.sort()

Sau đó bạn có thể lặp qua kv và làm bất cứ điều gì bạn muốn.

> kv.sort()
[ [ 'a', 'dsfdsfsdf' ],
  [ 'b', 'asdsad' ],
  [ 'c', 'masdas' ] ]


4

Đây là một phiên bản dựa trên lodash sạch hoạt động với các đối tượng lồng nhau

/**
 * Sort of the keys of an object alphabetically
 */
const sortKeys = function(obj) {
  if(_.isArray(obj)) {
    return obj.map(sortKeys);
  }
  if(_.isObject(obj)) {
    return _.fromPairs(_.keys(obj).sort().map(key => [key, sortKeys(obj[key])]));
  }
  return obj;
};

Sẽ còn sạch hơn nữa nếu lodash có toObject()phương pháp ...


3

Chỉ cần sử dụng lodash để giải nén bản đồ và sortBy giá trị đầu tiên của cặp và zip một lần nữa, nó sẽ trả về khóa đã sắp xếp.

Nếu bạn muốn giá trị sắp xếp thay đổi chỉ số cặp thành 1 thay vì 0

var o = { 'b' : 'asdsad', 'c' : 'masdas', 'a' : 'dsfdsfsdf' };
console.log(_(o).toPairs().sortBy(0).fromPairs().value())

nhập mô tả hình ảnh ở đây


Vui lòng sử dụng liên kết chỉnh sửa giải thích cách mã này hoạt động và không chỉ cung cấp mã, vì một lời giải thích có nhiều khả năng giúp người đọc trong tương lai. Xem thêm Cách trả lời . nguồn
Jed Fox

3

Sắp xếp các khóa đệ quy trong khi bảo quản tài liệu tham khảo.

function sortKeys(o){
    if(o && o.constructor === Array)
        o.forEach(i=>sortKeys(i));
    else if(o && o.constructor === Object)
        Object.entries(o).sort((a,b)=>a[0]>b[0]?1:-1).forEach(e=>{
            sortKeys(e[1]);
            delete o[e[0]];
            o[e[0]] = e[1];
        });
}

Thí dụ:

let x = {d:3, c:{g:20, a:[3,2,{s:200, a:100}]}, a:1};
let y = x.c;
let z = x.c.a[2];
sortKeys(x);
console.log(x); // {a: 1, c: {a: [3, 2, {a: 1, s: 2}], g: 2}, d: 3}
console.log(y); // {a: [3, 2, {a: 100, s: 200}}, g: 20}
console.log(z); // {a: 100, s: 200}

Đoạn trích hay! Mục đích của delete o[e[0]];nó là gì? Chúng ta không thể chỉ định?
Boyang

Có vẻ như chỉ có các bài tập mới cho các khóa không tồn tại sẽ nối thêm khóa vào cuối. Nếu xóa được nhận xét, các khóa sẽ không được sắp xếp, ít nhất là không có trong Chrome.
brunettdan

Điều đó có ý nghĩa. Cảm ơn! Trong mọi trường hợp, đây là một nguyên nhân bị mất vì các khóa đối tượng js không có trình tự, theo thông số kỹ thuật. Chúng tôi chỉ khai thác obj và chức năng đăng nhập chi tiết
Boyang

Phải, tôi sử dụng Bản đồ khi thứ tự các khóa rất quan trọng: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
trộm

3
Object.keys(unordered).sort().reduce(
    (acc,curr) => ({...acc, [curr]:unordered[curr]})
    , {}
)

3

Đây là một giải pháp nhẹ cho mọi thứ tôi cần để sắp xếp JSON.

function sortObj(obj) {
    if (typeof obj !== "object" || obj === null)
        return obj;

    if (Array.isArray(obj))
        return obj.map((e) => sortObj(e)).sort();

    return Object.keys(obj).sort().reduce((sorted, k) => {
        sorted[k] = sortObj(obj[k]);
        return sorted;
    }, {});
}

2

Sử dụng mã này nếu bạn có các đối tượng lồng nhau hoặc nếu bạn có mảng obj lồng nhau.

var sortObjectByKey = function(obj){
    var keys = [];
    var sorted_obj = {};
    for(var key in obj){
        if(obj.hasOwnProperty(key)){
            keys.push(key);
        }
    }
    // sort keys
    keys.sort();

    // create new array based on Sorted Keys
    jQuery.each(keys, function(i, key){
        var val = obj[key];
        if(val instanceof Array){
            //do for loop;
            var arr = [];
            jQuery.each(val,function(){
                arr.push(sortObjectByKey(this));
            }); 
            val = arr;

        }else if(val instanceof Object){
            val = sortObjectByKey(val)
        }
        sorted_obj[key] = val;
    });
    return sorted_obj;
};

5
Tác giả không nói rằng anh ta đang sử dụng jQuery, cũng không phải là câu hỏi được gắn thẻ jQuery. Sẽ thật tuyệt nếu bạn thêm một giải pháp trong javascript thuần túy.
rusmus

Cảm ơn @Phani đây chính xác là những gì tôi cần
Will Sheppard

2

Giải pháp:

function getSortedObject(object) {
  var sortedObject = {};

  var keys = Object.keys(object);
  keys.sort();

  for (var i = 0, size = keys.length; i < size; i++) {
    key = keys[i];
    value = object[key];
    sortedObject[key] = value;
  }

  return sortedObject;
}

// Test run
getSortedObject({d: 4, a: 1, b: 2, c: 3});

Giải trình:

Nhiều thời gian chạy JavaScript lưu trữ các giá trị bên trong một đối tượng theo thứ tự chúng được thêm vào.

Để sắp xếp các thuộc tính của một đối tượng theo các khóa của chúng, bạn có thể sử dụng hàm Object.keys sẽ trả về một mảng các khóa. Mảng khóa sau đó có thể được sắp xếp theo Array.prototype.sort () phương thức để sắp xếp các phần tử của một mảng (không cần gán chúng cho một biến mới).

Khi các khóa được sắp xếp, bạn có thể bắt đầu sử dụng từng cái một để truy cập nội dung của đối tượng cũ để điền vào một đối tượng mới (hiện đã được sắp xếp).

Dưới đây là một ví dụ về quy trình (bạn có thể kiểm tra nó trong các trình duyệt được nhắm mục tiêu của bạn):

/**
 * Returns a copy of an object, which is ordered by the keys of the original object.
 *
 * @param {Object} object - The original object.
 * @returns {Object} Copy of the original object sorted by keys.
 */
function getSortedObject(object) {
  // New object which will be returned with sorted keys
  var sortedObject = {};

  // Get array of keys from the old/current object
  var keys = Object.keys(object);
  // Sort keys (in place)
  keys.sort();

  // Use sorted keys to copy values from old object to the new one
  for (var i = 0, size = keys.length; i < size; i++) {
    key = keys[i];
    value = object[key];
    sortedObject[key] = value;
  }

  // Return the new object
  return sortedObject;
}

/**
 * Test run
 */
var unsortedObject = {
  d: 4,
  a: 1,
  b: 2,
  c: 3
};

var sortedObject = getSortedObject(unsortedObject);

for (var key in sortedObject) {
  var text = "Key: " + key + ", Value: " + sortedObject[key];
  var paragraph = document.createElement('p');
  paragraph.textContent = text;
  document.body.appendChild(paragraph);
}

Lưu ý: Object.keys là phương thức ECMAScript 5.1 nhưng đây là một polyfill cho các trình duyệt cũ hơn:

if (!Object.keys) {
  Object.keys = function (object) {
    var key = [];
    var property = undefined;
    for (property in object) {
      if (Object.prototype.hasOwnProperty.call(object, property)) {
        key.push(property);
      }
    }
    return key;
  };
}

2

Tôi đã chuyển một số enum Java sang các đối tượng javascript.

Những đối tượng trả lại mảng chính xác cho tôi. nếu các khóa đối tượng là loại hỗn hợp (chuỗi, int, char), có một vấn đề.

Types:

var TypeA = {
    "-1": "Any",
    "2": "2L",
    "100": "100L",
    "200": "200L",
    "1000": "1000L"
};

var TypeB = {
    "U": "Any",
    "W": "1L",
    "V": "2L",
    "A": "100L",
    "Z": "200L",
    "K": "1000L"
};


Sorted Keys(output):

Key list of TypeA -> ["-1", "2", "100", "200", "1000"]

Key list of TypeB -> ["U", "W", "V", "A", "Z", "K"]

2

Đoạn mã đơn giản và dễ đọc, sử dụng lodash.

Bạn chỉ cần đặt khóa trong dấu ngoặc kép khi gọi sortBy. Nó không phải được trích dẫn trong dữ liệu.

_.sortBy(myObj, "key")

Ngoài ra, tham số thứ hai của bạn để ánh xạ là sai. Nó nên là một chức năng, nhưng sử dụng pluck thì dễ dàng hơn.

_.map( _.sortBy(myObj, "key") , "value");

2

Có một dự án tuyệt vời của @sindresorhus được gọi là các phím sắp xếp hoạt động tuyệt vời.

Bạn có thể kiểm tra mã nguồn của nó ở đây:

https://github.com/sindresorhus/sort-keys

Hoặc bạn có thể sử dụng nó với npm:

$ npm install --save sort-keys

Đây cũng là ví dụ mã từ readme của anh ấy

const sortKeys = require('sort-keys');

sortKeys({c: 0, a: 0, b: 0});
//=> {a: 0, b: 0, c: 0}

sortKeys({b: {b: 0, a: 0}, a: 0}, {deep: true});
//=> {a: 0, b: {a: 0, b: 0}}

sortKeys({c: 0, a: 0, b: 0}, {
    compare: (a, b) => -a.localeCompare(b)
});
//=> {c: 0, b: 0, a: 0}

1

Câu trả lời thuần JavaScript để sắp xếp một đối tượng. Đây là câu trả lời duy nhất mà tôi biết sẽ xử lý các số âm. Hàm này dùng để sắp xếp các Đối tượng số.

Nhập obj = {1000: {}, -1200: {}, 10000: {}, 200: {}};

function osort(obj) {
var keys = Object.keys(obj);
var len = keys.length;
var rObj = [];
var rK = [];
var t = Object.keys(obj).length;
while(t > rK.length) {
    var l = null;
    for(var x in keys) {
        if(l && parseInt(keys[x]) < parseInt(l)) {
            l = keys[x];
            k = x;
        }
        if(!l) { // Find Lowest
            var l = keys[x];
            var k = x;
        }
    }
    delete keys[k];
    rK.push(l);
}

for (var i = 0; i < len; i++) {

    k = rK[i];
    rObj.push(obj[k]);
}
return rObj;
}

Đầu ra sẽ là một đối tượng được sắp xếp theo các số đó với các khóa mới bắt đầu từ 0.


1

Chỉ cần đơn giản hóa nó và làm cho câu trả lời rõ ràng hơn từ Matt Ball

//your object
var myObj = {
    b : 'asdsadfd',
    c : 'masdasaf',
    a : 'dsfdsfsdf'
  };

//fixed code
var keys = [];
for (var k in myObj) {
  if (myObj.hasOwnProperty(k)) {
    keys.push(k);
  }
}
keys.sort();
for (var i = 0; i < keys.length; i++) {
  k = keys[i];
  alert(k + ':' + myObj[k]);
}


1

Không chắc chắn nếu điều này trả lời câu hỏi, nhưng đây là những gì tôi cần.

Maps.iterate.sorted = function (o, callback) {
    var keys = Object.keys(o), sorted = keys.sort(), k; 
    if ( callback ) {
            var i = -1;
            while( ++i < sorted.length ) {
                    callback(k = sorted[i], o[k] );
            }
    }

    return sorted;
}

Được gọi là:

Maps.iterate.sorted({c:1, b:2, a:100}, function(k, v) { ... } ) 

1

Một dòng:

Object.entries(unordered)
  .sort(([keyA], [keyB]) => keyA > keyB)
  .reduce((obj, [key,value]) => Object.assign(obj, {[key]: value}), {})

1

cách tốt nhất để làm điều đó là

 const object =  Object.keys(o).sort().reduce((r, k) => (r[k] = o[k], r), {})

 //else if its in reverse just do 

 const object = Object.keys(0).reverse ()

Trước tiên, bạn có thể chuyển đổi đối tượng gần như mảng của mình thành một mảng thực và sau đó sử dụng .reverse ():

Object.assign([], {1:'banana', 2:'apple', 
3:'orange'}).reverse();
// [ "orange", "apple", "banana", <1 empty slot> ]

Vị trí trống ở cuối nếu nguyên nhân vì chỉ mục đầu tiên của bạn là 1 thay vì 0. Bạn có thể xóa vị trí trống bằng .length-- hoặc .pop ().

Ngoài ra, nếu bạn muốn mượn .reverse và gọi nó trên cùng một đối tượng, thì nó phải là một đối tượng giống như mảng đầy đủ. Đó là, nó cần một thuộc tính chiều dài:

Array.prototype.reverse.call({1:'banana', 2:'apple', 
3:'orange', length:4});
// {0:"orange", 1:"apple", 3:"banana", length:4}

Lưu ý rằng nó sẽ trả về cùng một đối tượng giống như mảng, vì vậy nó sẽ không phải là một mảng thực sự. Sau đó, bạn có thể sử dụng xóa để loại bỏ thuộc tính chiều dài.

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.