Urutkan objek JavaScript dengan kunci

532

Saya perlu mengurutkan objek JavaScript dengan kunci.

Maka berikut ini:

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

Akan menjadi:

{ 'a' : 'dsfdsfsdf', 'b' : 'asdsad', 'c' : 'masdas' }
vdh_ant
sumber
3
kemungkinan rangkap dari Menyortir objek JSON dalam Javascript
abraham
39
Kembali pada tahun 2011 (ketika pertanyaan ini diposting), spesifikasi ECMAScript mengatakan bahwa objek JavaScript tidak memiliki urutan bawaan - urutan yang diamati bergantung pada implementasi dan karenanya tidak dapat diandalkan. Namun, ternyata semua mesin JavaScript menerapkan semantik yang kurang lebih sama, sehingga sekarang telah distandarisasi dalam ES6 . Akibatnya, banyak jawaban di bawah ini yang digunakan benar sesuai spesifikasi, tetapi sekarang salah.
Mathias Bynens
dengan singkat mengatakan penggunaan diurutkan menjadi lebih rapat ketika Anda perlu membandingkan atau hash hasilnya: npmjs.com/package/json-stable-stringify
exebook
Mengingat bahwa objek hanya peta, atau dikte tergantung pada bahasa Anda, ada sedikit atau tidak ada alasan mengapa Anda melakukan ini. BAHWA BEGITU SAJA, Secara umum, urutan mereka disuntikkan ke dalam peta sebenarnya adalah urutan yang mereka tempati saat merangkai. SO, jika Anda membuat peta baru dan nilai-nilai yang diberikan berdasarkan daftar kunci yang dipilih, Anda akan menemukan sendiri peta yang diurutkan berdasarkan kunci
Fallenreaper
Perhatikan bahwa sejak Object.entriesdan Object.fromEntriesditambahkan ke JS, ini dapat dicapai dengan one-liner pendek yang bagus:Object.fromEntries(Object.entries(obj).sort())
Mike 'Pomax' Kamermans

Jawaban:

471

Jawaban lain untuk pertanyaan ini sudah usang, realitas implementasi tidak pernah cocok, dan secara resmi menjadi tidak benar sekarang karena spesifikasi ES6 / ES2015 telah diterbitkan.


Lihat bagian tentang urutan iterasi properti di Menjelajahi ES6 oleh Axel Rauschmayer :

Semua metode yang beralih pada kunci properti melakukannya dalam urutan yang sama:

  1. Pertama semua indeks Array, diurutkan secara numerik.
  2. Kemudian semua kunci string (yang bukan indeks), sesuai urutan pembuatannya.
  3. Lalu semua simbol, sesuai urutan pembuatannya.

Jadi ya, objek JavaScript yang sebenarnya memerintahkan, dan urutan kunci mereka / sifat dapat diubah.

Inilah cara Anda bisa mengurutkan objek berdasarkan kunci / propertinya, menurut abjad:

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"}'

Gunakan varalih-alih constuntuk kompatibilitas dengan mesin ES5.

Mathias Bynens
sumber
5
Saya benar-benar tidak bisa melihat perbedaan pada kode Anda dan jawaban teratas di sini selain menggunakan teknik pengulangan yang sedikit berbeda. Apakah benda-benda itu dapat dikatakan "dipesan" atau tidak tampaknya tidak relevan. Jawaban untuk pertanyaan ini masih sama. Spesifikasi yang dipublikasikan hanya menegaskan jawaban di sini.
Phil
6
FYI, telah diklarifikasi bahwa urutan enumerasi properti masih belum ditentukan: esdiscuss.org/topic/…
Felix Kling
6
@ Phil_1984_ Jawaban ini dan jawaban teratas sangat berbeda. Pertanyaan OP adalah bagaimana cara mengurutkan objek secara literal. Jawaban pilihan teratas mengatakan Anda tidak bisa, lalu memberikan solusi dengan menyimpan kunci yang diurutkan dalam array, kemudian iterasi dan mencetak pasangan nilai kunci dari array yang diurutkan. Jawaban ini mengklaim bahwa urutan literal objek sekarang dapat disortir dan contohnya menyimpan nilai kunci yang diurutkan kembali ke objek literal, lalu mencetak objek yang diurutkan secara langsung. Di samping catatan, alangkah baiknya jika situs yang tertaut masih ada.
cchamberlain
6
Kedua jawaban cukup menggunakan fungsi Array.sort untuk mengurutkan kunci terlebih dahulu. OP meminta untuk mengurutkan "objek JavaScript" dan hanya menggunakan JavaScript Object Notation (JSON) untuk menggambarkan 2 objek. Kedua objek ini secara logika identik artinya menyortir tidak relevan. Saya pikir jawaban teratas menjelaskan ini jauh lebih baik. Mengatakan "semua jawaban lain sekarang secara resmi salah" terlalu ekstrim bagi saya, terutama dengan tautan yang rusak. Saya pikir masalahnya adalah "spec ES6 baru ini" memberikan ilusi bahwa objek Javascript memiliki daftar kunci yang tidak benar.
Phil
1
Harap tambahkan bahwa solusi ini tidak didukung oleh berbagai browser modern (google "caniuse ES6"). Menggunakan jawaban ini hanya berisiko menemukan bug di browser tertentu saja (mis. Safari saat Chrome baik-baik saja).
Manuel Arwed Schmidt
244

Objek JavaScript 1 tidak dipesan. Tidak ada artinya mencoba "memilah" mereka. Jika Anda ingin mengulangi properti objek, Anda bisa mengurutkan kunci dan kemudian mengambil nilai terkait:

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


Implementasi alternatif menggunakan 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 Tidak ingin bertele-tele, tetapi tidak ada objek JSON .

Matt Ball
sumber
2
@MarcelKorpel Ada yang namanya objek JSON. Periksa bagian 8 dari JSON RFC resmi: ietf.org/rfc/rfc4627.txt
Paul
8
@Paulpro dua hal yang perlu diperhatikan tentang RFC itu: pertama, saat ini berusia 7 tahun, dan perbendaharaan kata berubah seiring waktu; kedua, "Memo ini memberikan informasi untuk komunitas Internet. Memo itu tidak menentukan standar Internet apa pun." Apakah urutan karakter yang diberikan mewakili objek JavaScript literal atau teks JSON tergantung pada konteks / penggunaan. Istilah "objek JSON" mengonfigurasikan dan membuat perbedaan menjadi ambigu dengan cara yang merugikan. Mari kita singkirkan terminologi yang tidak tepat, dan gunakan istilah yang lebih tepat jika memungkinkan. Saya tidak melihat alasan untuk melakukan sebaliknya. Kata-kata penting.
Matt Ball
6
@MattBall IMO JSON Object adalah istilah yang sangat tepat untuk string seperti {"a", 1}halnya JSON Array adalah istilah yang tepat untuk string seperti [1]. Sangat berguna untuk dapat berkomunikasi dengan mengatakan hal-hal seperti objek ketiga dalam array saya ketika Anda memiliki string [{x: 1}, {y: 2}, {z: 3}], jadi saya lebih suka "Itu bukan objek JSON" ketika berkomentar tentang literal Javascript, alih-alih "Tidak ada hal sebagai objek JSON ", yang hanya akan menyebabkan lebih banyak kebingungan dan kesulitan komunikasi nanti ketika OP sebenarnya bekerja dengan JSON.
Paul
3
@ Paulpro saya harus tidak setuju. {"a", 1}dapat berupa objek literal atau teks JSON (alias string JSON, jika Anda lebih suka). Yang tergantung pada konteks, yang pertama jika muncul kata demi kata dalam kode sumber JavaScript, yang kedua jika itu adalah string yang perlu diteruskan ke parser JSON untuk digunakan lebih lanjut. Ada perbedaan nyata antara keduanya ketika menyangkut sintaks yang diizinkan, penggunaan yang benar, dan serialisasi.
Matt Ball
4
Sekarang setelah ES6 / ES2015 diselesaikan, jawaban ini secara resmi menjadi salah. Lihat jawaban saya untuk info lebih lanjut.
Mathias Bynens
172

Banyak orang telah menyebutkan bahwa "objek tidak dapat diurutkan" , tetapi setelah itu mereka memberi Anda solusi yang berfungsi. Paradox, bukan?

Tidak ada yang menyebutkan mengapa solusi itu berhasil. Yaitu, karena di sebagian besar implementasi nilai-nilai browser dalam objek disimpan dalam urutan di mana mereka ditambahkan. Itu sebabnya jika Anda membuat objek baru dari daftar kunci yang disortir, itu mengembalikan hasil yang diharapkan.

Dan saya pikir kita bisa menambahkan satu lagi solusi - cara fungsional ES5:

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

Versi ES2015 di atas (diformat menjadi "satu-liner"):

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

Penjelasan singkat dari contoh di atas (seperti yang ditanyakan dalam komentar):

Object.keysmemberi kami daftar kunci pada objek yang disediakan ( objatau o), lalu kami menyortirnya menggunakan algoritma penyortiran default, selanjutnya .reducedigunakan untuk mengubah array itu kembali menjadi objek, tapi kali ini dengan semua kunci yang diurutkan.

nama kode-
sumber
7
@Pointy Perilaku ini selalu tersedia di semua browser utama, dan telah distandarisasi dalam ES6 / ES2015 . Saya akan mengatakan ini adalah saran yang bagus.
Mathias Bynens
3
Ini adalah cara paling sederhana dan paling ringkas untuk menyelesaikan tugas di EcmaScript v5. Agak terlambat ke pesta tetapi harus menjadi jawaban yang diterima.
Steven de Salas
2
"Ya, karena di sebagian besar nilai implementasi browser dalam objek disimpan dalam urutan di mana mereka ditambahkan" Namun hanya untuk properti non-numerik. Perhatikan juga bahwa masih belum ada jaminan pemesanan properti berulang (mis. Via for...in).
Felix Kling
2
Baik dari Anda untuk menjelaskan mengapa itu berhasil itu memberi pelajaran bagi saya. Terima kasih!
ola
5
Linter saya mengeluh tentang itu satu-liner (mengembalikan tugas), tetapi ini bekerja untuk saya dan lebih mudah bagi saya untuk membaca:Object.keys(dict).sort().reduce((r, k) => Object.assign(r, { [k]: dict[k] }), {});
aks.
68

Teman-teman saya secara kiasan terkejut! Tentu semua jawaban agak lama, tetapi tidak ada yang menyebutkan stabilitas dalam penyortiran! Jadi bersabarlah, saya akan mencoba yang terbaik untuk menjawab pertanyaan itu sendiri dan pergi ke detail di sini. Jadi saya akan minta maaf sekarang akan banyak dibaca.

Karena ini tahun 2018 saya hanya akan menggunakan ES6, semua Polyfill tersedia di dokumen MDN, yang akan saya tautkan pada bagian yang diberikan.


Jawab pertanyaan:

Jika kunci Anda hanya angka maka Anda dapat dengan aman menggunakannya Object.keys()bersama Array.prototype.reduce()untuk mengembalikan objek yang diurutkan:

// 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), {}));

Namun jika Anda bekerja dengan string, saya sangat menyarankan untuk merantai Array.prototype.sort()semua ini:

// 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), {}));

Jika seseorang bertanya-tanya pengurangan apa yang terjadi:

// 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().
}, {});

Jika diperlukan di sini adalah penjelasan untuk liner:

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.
  ,{}
);

Mengapa Penyortiran agak rumit:

Singkatnya Object.keys()akan mengembalikan array dengan urutan yang sama seperti yang kita dapatkan dengan loop normal:

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

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

Object.keys () mengembalikan array yang elemen-elemennya adalah string yang bersesuaian dengan properti enumerable yang ditemukan langsung pada objek. Urutan properti adalah sama dengan yang diberikan dengan mengulangi properti objek secara manual.

Sidenote - Anda dapat menggunakan Object.keys()pada array juga, perlu diingat indeks akan dikembalikan:

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

Tapi itu tidak semudah yang ditunjukkan oleh contoh-contoh itu, objek dunia nyata dapat berisi angka dan karakter alfabet atau bahkan simbol (tolong jangan lakukan itu).

Ini adalah contoh dengan semuanya dalam satu objek:

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

Sekarang jika kita gunakan Array.prototype.sort()pada array di atas perubahan output:

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

Berikut ini kutipan dari dokumen:

Metode sort () mengurutkan elemen-elemen dari array di tempat dan mengembalikan array. Semacam ini belum tentu stabil. Urutan penyortiran default adalah sesuai dengan poin kode Unicode string.

Kompleksitas waktu dan ruang dari jenis tidak dapat dijamin karena tergantung implementasi.

Anda harus memastikan bahwa salah satu dari mereka mengembalikan output yang diinginkan untuk Anda. Dalam contoh nyata, orang cenderung mencampuradukkan hal-hal secara khusus jika Anda menggunakan input informasi yang berbeda seperti API dan Database secara bersamaan.


Jadi apa masalahnya?

Ada dua artikel yang harus dipahami oleh setiap programmer:

Algoritma di tempat :

Dalam ilmu komputer, algoritma in-place adalah algoritma yang mengubah input tanpa menggunakan struktur data tambahan. Namun sejumlah kecil ruang penyimpanan tambahan diizinkan untuk variabel tambahan. Input biasanya ditimpa oleh output saat algoritma dijalankan. Algoritma in-place memperbarui urutan input hanya melalui penggantian atau pertukaran elemen. Algoritma yang tidak di tempat kadang-kadang disebut tidak di tempat atau di luar tempat.

Jadi pada dasarnya array lama kita akan ditimpa! Ini penting jika Anda ingin menyimpan array lama karena alasan lain. Jadi ingatlah ini.

Algoritma penyortiran

Algoritma sortir yang stabil mengurutkan elemen identik dalam urutan yang sama dengan yang muncul pada input. Saat mengurutkan beberapa jenis data, hanya sebagian dari data yang diperiksa saat menentukan urutan pengurutan. Misalnya, dalam contoh penyortiran kartu di sebelah kanan, kartu disortir berdasarkan pangkatnya, dan setelannya diabaikan. Ini memungkinkan beberapa versi berbeda yang diurutkan dengan benar dari daftar asli. Algoritma sorting yang stabil memilih salah satu dari ini, sesuai dengan aturan berikut: jika dua item membandingkan sama, seperti dua 5 kartu, maka urutan relatif mereka akan dipertahankan, sehingga jika satu datang sebelum yang lain dalam input, itu juga akan datang sebelum yang lain di output.

masukkan deskripsi gambar di sini

Contoh stabil pada kartu remi. Ketika kartu diurutkan berdasarkan peringkat dengan pengurutan yang stabil, kedua 5s harus tetap dalam urutan yang sama dalam output yang diurutkan di mana mereka awalnya masuk. Ketika mereka diurutkan dengan pengurutan yang tidak stabil, 5s mungkin berakhir sebaliknya. memesan dalam output yang diurutkan.

Ini menunjukkan bahwa penyortirannya benar tetapi itu berubah. Jadi di dunia nyata bahkan jika penyortirannya benar kita harus memastikan bahwa kita mendapatkan apa yang kita harapkan! Ini sangat penting mengingat hal ini juga. Untuk contoh JavaScript lainnya, lihat Array.prototype.sort () - docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Megajin
sumber
3
Anda flippin rock, terima kasih atas jawaban yang luar biasa ini. Salah satu yang terbaik yang pernah saya lihat di SO. Bersulang.
Gavin
Kalau saja Anda bisa memberikan metode freaking untuk digunakan di akhir. Jawaban yang bagus!
mmm
@momomo masalahnya adalah, tergantung pada apa yang Anda harapkan dari penyortiran, tidak ada metode yang tepat. Namun Anda hanya dapat menggunakan potongan kode dari jawaban saya: Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}).
Megajin
Bukankah stabilitas semacam itu tidak berlaku untuk pertanyaan ini: kami mengurutkan berdasarkan kunci objek, dan kuncinya unik. (Untuk memperpanjang contoh kartu Anda: tidak akan pernah ada dua 5 dalam paket, bahkan jika mereka dari jenis yang berbeda.)
Darren Cook
@ DarrenCook pertanyaan bagus! Anda benar, tidak akan pernah ada kunci yang sama dalam satu objek. Namun stabilitasnya lebih kompleks dari sekedar keunikan kunci. Sebagian besar waktu array disertakan dalam menyortir objek. Dan saat itulah semuanya bisa menjadi tidak stabil. Bayangkan permainan kartu dengan 5 pemain. Setiap tangan diwakili oleh array (untuk menjaga penyortiran tangan individu) dan kartu sebagai objek. Jika kartu Anda terlihat seperti ini {5: 'hearts'}atau {5: 'spades'}dan Anda mulai mengurutkan susunan kartu itu akan berpotensi tidak stabil dalam permainan seperti rummy. Belum lagi bahasa yang berbeda.
Megajin
29

Ini bekerja untuk saya

/**
 * 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;
};
Ashit Vora
sumber
10
Ini sebenarnya jawaban yang benar untuk pertanyaan yang ada. Untuk versi yang disederhanakan menggunakan Underscore, lihat: jsfiddle.net/wPjaQ/1
radicand
6
@radicand Tidak ada jawaban ini yang tidak benar. Ini mengembalikan objek baru, yang juga tidak memiliki urutan.
Paul
3
@radicand Tidak juga dalam praktiknya. Tidak ada yang namanya urutan pada kunci objek, jadi bagaimana Anda bisa mengatakan bahwa dalam praktiknya ini memberi Anda objek dalam urutan yang diurutkan? Itu benar-benar hanya memberi Anda kembali salinan dangkal dari objek yang Anda lewati.
Paul
9
Ini sangat salah. Mungkin terjadi untuk saat ini, tetapi akan pecah di browser web yang berbeda atau beban halaman yang berbeda di browser yang sama. Peramban dapat mengacak kunci objek untuk keamanan, atau saat Anda mengisi sebuah objek, itu akan menempatkan nilai-nilai ke dalam ember memori yang berbeda tergantung pada kunci, yang akan mengembalikan urutan yang berbeda. Jika ini berhasil, itu hanya keberuntungan bagi Anda.
1414
11
Ini juga memiliki penggunaan jQuery yang tidak perlu.
RobG
25

Ini tahun 2019 dan kami memiliki cara 2019 untuk menyelesaikan ini :)

Object.fromEntries(Object.entries({b: 3, a:8, c:1}).sort())
Ben
sumber
2
Bagaimana cara kami menyortir objek bersarang berdasarkan kunci?
a2441918
@ a2441918 Dengan cara yang sama seperti yang Anda lakukan dengan fungsi sort (). Silahkan lihat: developer.mozilla.org/de/docs/Web/JavaScript/Reference/… Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). Sort ((k, j ) => k - j))
user2912903
Untuk pengguna TypeScript ini belum tersedia untuk kami, lihat: github.com/microsoft/TypeScript/issues/30933
tsujp
Satu kalimat bagus, tapi bagaimana cara menyortir kunci dengan case-insensitive?
theMaxx
1
@theMaxx Gunakan fungsi kustom untuk menyortir, seperti: `` `Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). sort (([key1, val1], [key2, val2]) => key1.toLowerCase (). localeCompare (key2.toLowerCase ())))) `` `
Ben
22

di sini adalah 1 liner

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

sravan ganji
sumber
Apa-apaan sintaksis gila ini? (o[k] = v, o). Mengapa ini bekerja, di mana saya dapat menemukan dokumen tentangnya? Jelas mengembalikan parameter paling kanan, tetapi mengapa?
ntaso
1
@ tidak di sini
James
fungsi pendek pertama membuat o[k]sama dengan vdan kemudian kembalio
Tahsin Turkoz
19

Ini adalah pertanyaan lama, tetapi mengambil isyarat dari jawaban Mathias Bynens ', saya telah membuat versi pendek untuk mengurutkan objek saat ini , tanpa banyak overhead.

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

setelah eksekusi kode, objek "tidak berurutan" itu sendiri akan memiliki kunci yang diurutkan berdasarkan abjad.

Sergio Moura
sumber
17

Menggunakan lodash ini akan bekerja:

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

Hanya makanan untuk dipikirkan.

Brian M. Hunt
sumber
15

Misalkan itu bisa berguna dalam VisualStudio debugger yang menunjukkan properti objek yang tidak terurut.

(function(s){var t={};Object.keys(s).sort().forEach(function(k){t[k]=s[k]});return t})({b:2,a:1,c:3})
Serg
sumber
So Great Thanks a loooot
Mugiwara
Bagus! Terima kasih atas solusi ringkas ini.
Con Antonakos
9

Versi garis bawah :

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

Jika Anda tidak mempercayai peramban Anda untuk menjaga urutan kunci, saya sangat menyarankan untuk mengandalkan array array berpasangan dengan nilai kunci.

_.sortBy(_.pairs(c),function(o){return o[0]})
Flavien Volken
sumber
Lebih baik:_.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,
});
pengguna3286817
sumber
Mungkin menambahkan beberapa penjelasan tentang kode Anda lebih baik.
aristotll
1
Mendapat kunci objek, jadi itu adalah array dari string, saya mengurutkan () mereka dan karena itu adalah array dari string (kunci) saya menguranginya (dengan mengurangi () dari js Array). Acc awalnya adalah objek kosong {} (argumen terakhir dari reducer) dan reducer (callback) memberikan pada objek kosong nilai-nilai dari objek obj dengan urutan kunci yang diurutkan.
user3286817
8

Mungkin bentuk yang sedikit lebih elegan:

 /**
     * 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 dan sama dengan sintaks ES6 +:

function ksort( src ) {
  const keys = Object.keys( src );
  keys.sort();
  return keys.reduce(( target, key ) => {
        target[ key ] = src[ key ];
        return target;
  }, {});
};
Dmitry Sheiko
sumber
itu tidak ada artinya. Anda masih mengembalikan objek. Anda tidak dapat menjamin objek di target Anda benar-benar akan memiliki pesanan. Anda harus mengembalikan array. Astaga.
mmm
satu-satunya hal yang Anda lakukan di sini adalah memastikan itu satu set, dengan cara yang tidak optimal.
mmm
7

pengurutan rekursif, untuk objek dan array bersarang

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!'
            }
        },
    ]
});
pengguna3286817
sumber
Saya pikir Anda perlu elsedi sana - bisa benar untuk keduanya Array.isArray(obj[key])dan untuktypeof obj[key] === 'object'
jononomo
Ketika Anda memiliki array primitif, fungsi Anda mengubah primitif (string / angka) menjadi objek kosong. Untuk menangkap ini saya menambahkan hak berikut di awal fungsi Anda function sortObjectKeys(obj){:: if(typeof obj != 'object'){ /* it is a primitive: number/string (in an array) */ return obj; }. Untuk ketahanan saya pada awal lengkap juga menambahkan:if(obj == null || obj == undefined){ return obj; }
pergi
4

Seperti yang telah disebutkan, objek tidak berurutan.

Namun...

Anda mungkin menemukan idiom ini berguna:

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

var kv = [];

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

kv.sort()

Anda kemudian dapat beralih melalui kv dan melakukan apapun yang Anda inginkan.

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

Berikut ini adalah versi berbasis Lodash bersih yang berfungsi dengan objek bersarang

/**
 * 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;
};

Akan lebih bersih jika lodash memiliki toObject()metode ...

BlueRaja - Danny Pflughoeft
sumber
3

Cukup gunakan lodash untuk unzip peta dan urutkan oleh nilai pertama pasangan dan zip lagi itu akan mengembalikan kunci yang diurutkan.

Jika Anda ingin nilai pengubahan nilai indeks pasangan menjadi 1, bukan 0

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

masukkan deskripsi gambar di sini

Narayanaperumal Gurusamy
sumber
Harap gunakan tautan edit untuk menjelaskan cara kerja kode ini dan jangan hanya memberikan kode, karena penjelasan lebih memungkinkan untuk membantu pembaca di masa mendatang. Lihat juga Cara Menjawab . sumber
Jed Fox
3

Mengurutkan kunci secara rekursif sambil mempertahankan referensi.

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

Contoh:

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}
brunettdan
sumber
Cuplikan yang bagus! Apa tujuan dari delete o[e[0]];sana? Tidak bisakah kita menetapkan saja?
Boyang
Sepertinya hanya tugas baru untuk kunci yang tidak ada yang akan menambahkan kunci di akhir. Jika penghapusan dikomentari, kunci tidak akan diurutkan, setidaknya tidak di Chrome.
brunettdan
itu masuk akal. Terima kasih! Bagaimanapun, ini adalah penyebab yang hilang karena kunci objek js tidak memiliki urutan, sesuai dengan spesifikasi. Kami hanya mengeksploitasi rincian fungsi obj dan log
Boyang
Ya, saya menggunakan Peta ketika urutan kunci penting: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
brunettdan
3
Object.keys(unordered).sort().reduce(
    (acc,curr) => ({...acc, [curr]:unordered[curr]})
    , {}
)
Wildhammer
sumber
3

Ini adalah solusi ringan untuk semua yang saya butuhkan untuk menyortir 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;
    }, {});
}
Alan Hape
sumber
2

Gunakan kode ini jika Anda memiliki objek bersarang atau jika Anda memiliki objek array bersarang.

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;
};
Phani Reddy
sumber
5
Penulis tidak menyatakan mengatakan bahwa ia menggunakan jQuery, juga tidak ada pertanyaan yang ditandai jQuery. Akan lebih baik jika Anda menambahkan solusi dalam javascript murni.
rusmus
Terima kasih @Phani, inilah yang saya butuhkan
Will Sheppard
2

Larutan:

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

Penjelasan:

Banyak runtimes JavaScript menyimpan nilai di dalam objek sesuai urutan penambahannya.

Untuk mengurutkan properti suatu objek dengan kunci mereka, Anda dapat menggunakan fungsi Object.keys yang akan mengembalikan array kunci. Array kunci kemudian dapat diurutkan berdasarkan Array.prototype.sort () yang mengurutkan elemen-elemen array di tempat (tidak perlu menempatkan mereka ke variabel baru).

Setelah tombol diurutkan, Anda dapat mulai menggunakannya satu per satu untuk mengakses konten objek lama untuk mengisi objek baru (yang sekarang disortir).

Di bawah ini adalah contoh prosedur (Anda dapat mengujinya di browser yang ditargetkan):

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

Catatan: Object.keys adalah metode ECMAScript 5.1 tetapi di sini ada polyfill untuk peramban yang lebih lama:

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;
  };
}
Benny Neugebauer
sumber
2

Saya mentransfer beberapa enum Java ke objek javascript.

Objek-objek ini mengembalikan array yang benar untuk saya. jika kunci objek adalah tipe campuran (string, int, char), ada masalah.

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"]
Sherali Turdiyev
sumber
2

Cuplikan sederhana dan mudah dibaca, menggunakan lodash.

Anda harus memasukkan kunci dalam tanda kutip hanya saat memanggil sortBy. Itu tidak harus dalam tanda kutip dalam data itu sendiri.

_.sortBy(myObj, "key")

Juga, parameter kedua Anda untuk memetakan salah. Seharusnya fungsi, tetapi menggunakan memetik lebih mudah.

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

Ada proyek hebat oleh @sindresorhus yang disebut sort-keys yang bekerja dengan sangat baik.

Anda dapat memeriksa kode sumbernya di sini:

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

Atau Anda dapat menggunakannya dengan npm:

$ npm install --save sort-keys

Berikut juga contoh kode dari readme-nya

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}
fernandopasik
sumber
1

JavaScript murni menjawab untuk mengurutkan Objek. Ini adalah satu-satunya jawaban yang saya tahu yang akan menangani angka negatif. Fungsi ini untuk menyortir Objek numerik.

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

Output akan menjadi objek yang diurutkan berdasarkan angka-angka itu dengan kunci baru mulai dari 0.

Kasus
sumber
1

Hanya untuk menyederhanakannya dan membuatnya lebih jelas jawaban dari 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]);
}

João Pimentel Ferreira
sumber
1

Tidak yakin apakah ini menjawab pertanyaan, tetapi inilah yang saya butuhkan.

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

Disebut sebagai:

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

Satu baris:

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

cara terbaik untuk melakukannya adalah

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

Pertama-tama Anda dapat mengonversi objek yang hampir mirip array menjadi array nyata, dan kemudian menggunakan .reverse ():

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

Slot kosong di bagian akhir jika disebabkan karena indeks pertama Anda adalah 1 bukan 0. Anda dapat menghapus slot kosong dengan .length-- atau .pop ().

Atau, jika Anda ingin meminjam .reverse dan menyebutnya pada objek yang sama, itu harus objek yang sepenuhnya seperti array. Artinya, perlu properti panjang:

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

Catatan itu akan mengembalikan objek objek yang sepenuhnya seperti array, sehingga tidak akan menjadi array nyata. Anda kemudian dapat menggunakan delete untuk menghapus properti panjang.

Pedro JR
sumber