JavaScript nesnesini anahtara göre sırala


532

JavaScript nesnelerini anahtarla sıralamam gerekiyor.

Dolayısıyla aşağıdakiler:

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

Olacaktı:

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


39
2011 yılında (bu soru yayınlandığında), ECMAScript spekülasyonu, JavaScript nesnelerinin doğal bir sıraya sahip olmadığını söyledi - gözlemlenen sipariş uygulamaya bağlıydı ve bu nedenle güvenilemedi. Ancak, aynı semantiklerin aşağı yukarı aynı semantik olarak uygulandığı tüm JavaScript motorları olduğu için, bunlar artık ES6'da standartlaştırılmıştır . Sonuç olarak, aşağıdaki cevapların çoğu spesifikasyona göre doğruydu, ancak şimdi yanlış.
Mathias Bynens

Kısaca söyleyerek sonuçları karşılaştırmanız veya hash etmeniz gerektiğinde sıralanmış stringify'ı kullanın: npmjs.com/package/json-stable-stringify
exebook

Nesnelerin sadece harita olduğu veya dilinize bağlı olarak dikte ettiği göz önüne alındığında, bunu yapmanıza gerek yoktur. DESTEKLENENLER Genellikle, bir haritaya enjekte edildikleri sıra aslında dizgi yaparken ikamet ettikleri sıradır. Bu nedenle, yeni bir harita oluşturduysanız ve sunulan bir anahtar listesine göre değerler atadıysanız, kendinize anahtarlara dayalı sıralı bir harita bulacaksınız
Fallenreaper

O zamandan beri o Not Object.entriesve Object.fromEntriesJS eklenmiş, bu güzel bir şekilde kısa bir astar ile elde edilebilir:Object.fromEntries(Object.entries(obj).sort())
Mike 'Po max' Kamermans

Yanıtlar:


471

Bu soruya verilen diğer cevaplar eskimiş, asla eşlenmemiş uygulama gerçekliği ve ES6 / ES2015 spesifikasyonu yayınlandığı için resmen yanlış oldu.


Bkz bölümüne mülkiyet yineleme sırayla içinde ES6 keşfetmek Axel Rauschmayer tarafından :

Özellik anahtarları üzerinden yineleme yapan tüm yöntemler bunu aynı sırayla yapar:

  1. İlk önce tüm Array indeksleri sayısal olarak sıralanmıştır.
  2. Sonra tüm dize anahtarları (indeks olmayan), oluşturuldukları sırayla.
  3. Sonra tüm semboller oluşturuldukları sırayla.

Yani evet, JavaScript nesneleri vardır aslında sipariş ve onların tuşlarının sırası / özellikleri değiştirilebilir içinde.

Bir nesneyi anahtarlarına / özelliklerine göre alfabetik olarak nasıl sıralayabileceğiniz aşağıda açıklanmıştır:

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

ES5 motorlarıyla uyumluluk varyerine kullanın const.


5
Gerçekten biraz farklı bir döngü tekniği kullanmak dışında kod ve üst yanıt burada bir fark göremiyorum. Nesnelerin "sipariş edildiği" söylenip söylenmeyeceği alakasız görünmektedir. Bu sorunun cevabı hala aynı. Yayınlanan spesifikasyon sadece cevapları onaylar.
Phil

6
Bilginize, mülklerin numaralandırma düzeninin hala tanımlanmamış olduğu açıklandı
Felix Kling

6
@ Phil_1984_ Bu cevap ve en çok oy alan cevap çok farklı. OP'nin sorusu, bir nesne değişmezinin nasıl sıralanacağıydı. En çok oy alan cevap, yapamayacağınızı söyler, ardından sıralı anahtarları bir dizide saklayıp, sıralanan diziden anahtar / değer çiftlerini yineleyip yazdırarak bir geçici çözüm sağlar. Bu yanıt, nesne değişmezlerinin sırasının artık sıralanabilir olduğunu ve örneğinin sıralanmış anahtar değerlerini bir nesne değişmezine depoladığını ve ardından sıralanmış nesneyi doğrudan yazdırdığını iddia ediyor. Bir yan notta, bağlantılı sitenin hala mevcut olması iyi olurdu.
cchamberlain

6
Her iki yanıt da önce anahtarları sıralamak için Array.sort işlevini kullanır. OP bir "JavaScript nesnesi" sıralamak istiyor ve sadece 2 nesneyi tanımlamak için JavaScript Nesne Notasyonu (JSON) kullanıyor. Bu 2 nesne mantıksal olarak aynıdır, yani sıralama önemsizdir. Bence en iyi cevap bunu çok daha iyi açıklıyor. "Diğer tüm cevaplar artık resmen yanlış" demek benim için çok zor, özellikle de kopuk bir bağlantıyla. Sorun "bu yeni ES6 spec" Javascript nesneleri sadece doğru değil tuşları sıralı bir liste var yanılsaması olduğunu düşünüyorum.
Phil

1
Lütfen bu çözümün çeşitli modern tarayıcılar tarafından desteklenmediğini (google "caniuse ES6") ekleyin. Bu yanıtların kullanılması, yalnızca belirli tarayıcılarda bulunması zor hatalarla karşılaşır (örneğin, Chrome iyi olduğunda Safari).
Manuel Arwed Schmidt

244

JavaScript nesneleri 1 sipariş edilmez. Onları "sıralamaya" çalışmak anlamsızdır. Bir nesnenin özellikleri üzerinde yineleme yapmak isterseniz, tuşları sıralayabilir ve ardından ilişkili değerleri alabilirsiniz:

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


Object.keysFantezi kullanarak alternatif uygulama :

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 Bilgiçlik taslamamak, ancak JSON nesnesi diye bir şey yoktur .


2
@MarcelKorpel JSON nesnesi diye bir şey var. Resmi JSON RFC'nin 8. bölümünü kontrol edin: ietf.org/rfc/rfc4627.txt
Paul

8
@Paulpro bu RFC hakkında dikkat edilmesi gereken iki şey: ilk olarak, bu noktada 7 yaşında ve kelime bilgisi zamanla değişiyor; ikincisi, "Bu not İnternet topluluğu için bilgi sağlar. Hiçbir türde bir İnternet standardı belirtmez." Belirli bir karakter dizisinin bir JavaScript nesnesi değişmezini mi yoksa JSON metnini mi temsil ettiği bağlama / kullanıma bağlıdır. "JSON nesnesi" terimi, ayrımı zararlı bir şekilde karıştırır ve belirsizleştirir. Kesin olmayan terminolojiden kurtulalım ve mümkünse daha kesin bir terim kullanalım. Aksini yapmak için hiçbir neden göremiyorum. Kelimeler önemlidir.
Matt Ball

6
@MattBall IMO JSON Nesnesi, {"a", 1}tıpkı JSON Dizisi gibi bir dize için kesin bir terimdir [1]. Dizeye sahip olduğunuzda dizimdeki üçüncü nesne gibi şeyler söyleyerek iletişim kurabilmek yararlıdır [{x: 1}, {y: 2}, {z: 3}], bu yüzden bir Javascript değişmezi hakkında yorum yaparken "Bu bir JSON nesnesi değil" i tercih ederim. "JSON nesnesi olarak bir şey", OP daha sonra aslında JSON ile çalışırken daha fazla karışıklık ve iletişim zorluklarına neden olacak.
Paul

3
@Paulpro Kabul etmemeliyim. {"a", 1}bir nesne değişmezi veya bir JSON metnidir (gerçekten tercih ederseniz JSON dizesi olarak da bilinir). Hangi bağlamına bağlıdır, birincisi JavaScript kaynak kodunda kelimesi kelimesine görünürse, ikincisi daha sonra kullanılmak üzere bir JSON ayrıştırıcısına iletilmesi gereken bir dizedir. İzin verilen sözdizimi, doğru kullanım ve serileştirme söz konusu olduğunda ikisi arasında gerçek farklılıklar vardır.
Matt Ball

4
Artık ES6 / ES2015 tamamlandığına göre, bu cevap resmen yanlış oldu. Daha fazla bilgi için cevabıma bakın.
Mathias Bynens

172

Birçok insan "nesneler sıralanamaz" dan bahsettiler , ancak bundan sonra size çalışan bir çözüm veriyorlar. Paradoks, değil mi?

Kimse bu çözümlerin neden işe yaradığını söylemiyor. Bunlar, tarayıcının uygulamalarının çoğunda nesnelerdeki değerler eklendikleri sıraya göre depolanır. Bu nedenle, sıralı anahtar listesinden yeni bir nesne oluşturursanız, beklenen bir sonuç döndürülür.

Ve bir çözüm daha ekleyebileceğimizi düşünüyorum - ES5 fonksiyonel yolu:

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

Yukarıdaki ES2015 sürümü ("tek astarlı" olarak biçimlendirilmiş):

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

Yukarıdaki örneklerin kısa açıklaması (yorumlarda belirtildiği gibi):

Object.keysbize sağlanan nesnede ( objveya o) anahtarların bir listesini veriyorsa , varsayılan sıralama algoritmasını kullananları sıralıyoruz, daha sonra .reducebu diziyi bir nesneye geri dönüştürmek için kullanılıyor, ancak bu sefer tüm anahtarlar sıralandı.


7
@Pointy Bu davranış tüm büyük tarayıcılarda her zaman mevcuttur ve ES6 / ES2015'te standartlaştırılmıştır . Bunun iyi bir tavsiye olduğunu söyleyebilirim.
Mathias Bynens

3
Bu, EcmaScript v5'te görevi gerçekleştirmenin en basit ve en kısa yoludur. Partiye biraz geç ama kabul edilen cevap olmalı.
Steven de Salas

2
"Bunlar, çünkü tarayıcının uygulamalarının çoğunda nesnelerdeki değerler eklendikleri sıraya göre saklanır." Ancak sayısal olmayan özellikler için. Ayrıca, özelliklerin hangi sırayla yinelendiğine dair hala bir garanti olmadığına dikkat edin (örn for...in.
Felix Kling

2
Neden işe yaradığını açıklamaktan hoşlanıyordum, benim için ders yaptı. Teşekkürler!
ola

5
Linterim bu tek astardan şikayet etti (bir ödev iade), ama bu benim için çalışıyor ve okumam daha kolay:Object.keys(dict).sort().reduce((r, k) => Object.assign(r, { [k]: dict[k] }), {});
aks.

68

Çocuklar mecazi olarak şok oldum! Elbette tüm cevaplar biraz eski, ama kimse sıralamadaki istikrardan bile bahsetmedi! Öyleyse bana sor, sorunun kendisine cevap vermek ve burada ayrıntılara girmek için elimden geleni yapacağım. Şimdi özür dileyeceğim şimdi okuyacak çok şey olacak.

2018 olduğundan sadece ES6 kullanacağım, Çoklu Doldurmaların tümü, verilen bölümde bağlayacağım MDN belgelerinde mevcuttur.


Sorunun cevabı:

Anahtarlarınız yalnızca rakamsa , sıralanan nesneyi döndürmek için Object.keys()ile birlikte güvenle kullanabilirsiniz Array.prototype.reduce():

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

Ancak dizeleri ile çalışıyorsanız Array.prototype.sort()tüm bunların içine zincirleme tavsiye ederim :

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

Birisi azaltmanın ne yaptığını merak ediyorsa:

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

Gerekirse burada bir astar için açıklama:

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

Sıralama neden biraz karmaşık:

Kısacası Object.keys(), normal bir döngü ile elde ettiğimiz sırayla bir dizi döndürür:

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

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

Object.keys (), öğeleri doğrudan nesne üzerinde bulunan numaralandırılabilir özelliklere karşılık gelen dizeler olan bir dizi döndürür. Özelliklerin sırası, nesnenin özellikleri üzerinde elle döngü yapılarak verilenle aynıdır.

Sidenote - Dizilerde de kullanabilirsiniz Object.keys(), dizinin döndürüleceğini unutmayın:

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

Ancak bu örneklerde gösterildiği gibi kolay değildir, gerçek dünya nesneleri sayılar ve alfabetik karakterler veya hatta semboller içerebilir (lütfen yapmayın).

Hepsi tek bir nesnede olan bir örnek:

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

Şimdi Array.prototype.sort()yukarıdaki dizide kullanırsak , çıktı değişir:

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

İşte dokümanlardan bir alıntı:

Sort () yöntemi, bir dizinin öğelerini yerinde sıralar ve diziyi döndürür. Sıralama mutlaka sabit değildir. Varsayılan sıralama düzeni Unicode kod noktalarına göre yapılır.

Bu türün zaman ve mekan karmaşıklığı, uygulamaya bağlı olduğu için garanti edilemez.

Bunlardan birinin sizin için istenen çıktıyı verdiğinden emin olmalısınız. Gerçek hayattaki örneklerde, API'lar ve Veritabanları gibi farklı bilgi girişlerini birlikte kullanırsanız, insanlar özel olarak işleri bir araya getirme eğilimindedir.


Peki önemli olan ne?

Her programcının anlaması gereken iki makale var:

Yerinde algoritma :

Bilgisayar biliminde, yerinde algoritma, yardımcı veri yapısı olmadan girişi dönüştüren bir algoritmadır. Ancak yardımcı değişkenler için az miktarda ekstra depolama alanına izin verilir. Algoritma yürütülürken giriş genellikle çıktı tarafından yazılır. Yerinde algoritma, giriş sırasını yalnızca öğelerin değiştirilmesi veya değiştirilmesi yoluyla günceller. Yerinde olmayan bir algoritmaya bazen yerinde değil veya yerinde değil denir.

Yani temelde eski dizimizin üzerine yazılacak! Eski diziyi başka nedenlerle korumak istiyorsanız bu önemlidir. Bunu aklınızda bulundurun.

Sıralama algoritması

Kararlı sıralama algoritmaları, özdeş öğeleri girişte göründükleri sırayla sıralar. Bazı veri türlerini sıralarken, sıralama düzenini belirlerken verilerin yalnızca bir kısmı incelenir. Örneğin, sağdaki kart sıralama örneğinde, kartlar sıralarına göre sıralanır ve takımları yoksayılır. Bu, orijinal listenin doğru şekilde sıralanmış birden fazla farklı versiyonuna olanak tanır. Kararlı sıralama algoritmaları, bunlardan birini aşağıdaki kurala göre seçer: iki öğe, iki 5 kart gibi eşit olarak karşılaştırılırsa, göreli sıraları korunur, böylece girişte biri diğerinden önce gelirse, aynı zamanda çıktıda diğerinden önce gelir.

resim açıklamasını buraya girin

Oyun kartlarında kararlı sıralama örneği. Kartlar kararlı bir sıralama ile sıralamaya göre sıralandıklarında, iki 5'lerin başlangıçta oldukları sıralı çıkışta aynı sırada kalmaları gerekir. Kararlı olmayan bir sıralamada sıralandıklarında, 5'ler ters yönde bitebilir sıralı çıktıda sırala.

Bu, sıralamanın doğru olduğunu ancak değiştiğini gösterir. Bu yüzden gerçek dünyada sıralama doğru olsa bile beklediğimizden emin olmalıyız! Bu çok önemlidir, bunu aklınızda bulundurun. Daha fazla JavaScript örneği için Array.prototype.sort () - dokümanlarına bakın: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort


3
Kayayı çeviriyorsun, bu inanılmaz cevap için teşekkür ederim. SO üzerinde gördüğüm en iyi biri. Şerefe.
Gavin

Sonunda kullanmak için sadece bir ucube yöntemi sağlayabilir. Büyük cevap olsa!
mmm

momomo sorun, sıralamadan ne beklediğinize bağlı olarak, doğru bir yöntem yoktur. Ancak sadece cevabım Bu kod parçasını kullanabilirsiniz: Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {}).
Megajin

Sıralamanın kararlılığı bu soru için geçerli değil: nesne anahtarına göre sıralıyoruz ve anahtar benzersizdir. (Kart örneğinizi genişletmek için: farklı kıyafetler olsalar bile, pakette asla iki 5 olamaz.)
Darren Cook

@DarrenCook iyi soru! Haklısın, bir nesnede asla aynı anahtar olmayacak. Bununla birlikte, kararlılık sadece bir anahtarın benzersizliğinden daha karmaşıktır. Çoğu zaman bir dizi nesneleri sıralamada bulunur. Ve o zaman her şey kararsız hale gelebilir. 5 oyunculu bir kart oyunu düşünün. Her el bir dizi (bireysel el sıralamasını korumak için) ve kartlar nesne olarak temsil edilir. Kartınız buna benziyorsa {5: 'hearts'}veya {5: 'spades'}diziyi sıralamaya başlarsanız, remi gibi oyunlarda potansiyel olarak kararsız hale gelir. Farklı dillerden bahsetmiyorum.
Megajin

29

Bu benim için çalışıyor

/**
 * 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
Bu aslında eldeki soruya doğru cevaptır. Underscore kullanarak basitleştirilmiş bir versiyon için bakınız: jsfiddle.net/wPjaQ/1
radicand

6
@radicand Hayır, bu cevap doğru değil. Sırası da olmayan yeni bir nesne döndürür.
Paul

3
@radicand Pratikte de değil. Nesne anahtarlarında düzen diye bir şey yoktur, bu yüzden pratikte bunun bir nesneyi sıralı bir düzende verdiğini nasıl söyleyebilirsiniz? Bu gerçekten size ilettiğiniz nesnenin sığ bir kopyasını geri veriyor.
Paul

9
Bu çok yanlış. Şimdilik işe yarayabilir, ancak farklı bir web tarayıcısında veya aynı tarayıcıda farklı bir sayfa yüklemesinde kırılacaktır. Tarayıcılar, güvenlik için nesne anahtarlarını rastgele ayarlayabilir veya bir nesneyi doldururken, farklı bir sıra döndürecek olan değerlere bağlı olarak değerleri farklı bellek gruplarına koyacaktır. Bu işe yararsa sizin için şanslı.
Yobert

11
Ayrıca jQuery gereksiz yere kullanımı vardır.
RobG

25

2019 ve bunu çözmenin 2019 bir yolu var :)

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

2
Yuvalanmış nesneleri tuşa göre nasıl sıralarız?
a2441918

@ a2441918 sort () işleviyle aynı şekilde. Bir göz atın: developer.mozilla.org/de/docs/Web/JavaScript/Reference/… Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). Sort ((k, j ) => k - j))
user2912903

TypeScript kullanıcıları için bu henüz bizim için mevcut değil, bkz: github.com/microsoft/TypeScript/issues/30933
tsujp

Güzel bir astar, ama tuşları büyük / küçük harfe duyarlı olmayan bir şekilde nasıl sıralayabilirim?
theMaxx

1
@theMaxx Sıralama için özel bir işlev kullanın: `` Object.fromEntries (Object.entries ({b: 3, a: 8, c: 1}). sort (([key1, val1], [key2, val2]) => key1.toLowerCase (). localeCompare (key2.toLowerCase ()))) ``
Ben

22

işte 1 astar

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


Bu çılgın sözdizimi nedir? (o[k] = v, o). Bu neden işe yarıyor, bununla ilgili belgeleri nerede bulabilirim? Açıkçası en sağdaki parametreyi döndürür, ama neden?
ntaso

1
@ntaso burada
James

kısa fonksiyon önce o[k]eşittir vve sonra geri dönero
Tahsin Turkoz

19

Bu eski bir soru, ama Mathias Bynens'in cevabından ipucunu alarak, fazla yük olmadan mevcut nesneyi sıralamak için kısa bir versiyon yaptım .

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

kod yürütüldükten sonra "sırasız" nesnenin kendisi anahtarları alfabetik olarak sıralayacaktır.


17

Lodash kullanarak bu işe yarayacak:

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

Düşünce için sadece yiyecek.


15

Sırasız nesne özelliklerini gösteren VisualStudio hata ayıklayıcısında yararlı olabileceğini varsayalım.

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

Çok büyük bir loooot teşekkürler
Mugiwara

Güzel! Bu özlü çözüm için teşekkür ederim.
Con Antonakos

9

Alt çizgi sürümü :

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

Tarayıcınızın anahtarların sırasını koruduğu konusunda güvenmiyorsanız, sipariş edilen anahtar / değer çifti eşleştirilmiş dizilerine güvenmenizi önemle tavsiye ederim.

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

Daha iyi:_.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,
});

Belki kodunuzla ilgili bazı açıklamalar eklemek daha iyidir.
aristotll

1
Nesnenin anahtarlarını alır, bu yüzden dizelerin dizisidir, onları sıralar () ve dizeleri (anahtarlar) dizisi olarak (js Array'ın azaltma () ile) azaltırım. Acc başlangıçta boş bir nesnedir {} (redüktörün son argümanı) ve redüktör (geri arama) boş nesneye kaynak anahtarın değerlerini sıralı anahtar dizisiyle atar.
user3286817

8

Belki biraz daha zarif bir form:

 /**
     * 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 ve ES6 + sözdizimi ile aynı:

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

hiçbir şey sıralamıyor. hala bir nesneyi döndürüyorsunuz. hedefinizdeki nesnelerin aslında herhangi bir emri olacağını garanti edemezsiniz. bir dizi döndürmeniz gerekir. jeeezus.
mmm

Burada yaptığınız tek şey, bunun en uygun olmayan bir şekilde bir set olmasını sağlamaktır.
mmm

7

iç içe nesne ve diziler için özyinelemeli sıralama

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

Senin bir ihtiyacın var elseikisi için de geçerli olabilir - orada Array.isArray(obj[key])ve içintypeof obj[key] === 'object'
jononomo

Bir dizi temel öğe olduğunda, işleviniz temel öğeleri (dize / sayı) boş nesnelere dönüştürür. Bunu yakalamak için fonksiyonunuzun başına aşağıdakileri ekledim function sortObjectKeys(obj){:: if(typeof obj != 'object'){ /* it is a primitive: number/string (in an array) */ return obj; }. Sağlamlık için tam başlangıçta da ekledi:if(obj == null || obj == undefined){ return obj; }
isgoed

4

Daha önce de belirtildiği gibi, nesneler sıralanmamıştır.

Ancak...

Bu deyimi yararlı bulabilirsiniz:

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

var kv = [];

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

kv.sort()

Daha sonra kv ile tekrarlayabilir ve ne istersen yapabilirsin.

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


4

İç içe nesnelerle çalışan temiz, lodash tabanlı bir sürüm

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

Lodash'ın bir toObject()yöntemi olsaydı daha temiz olurdu ...


3

Sadece harita açmak ve sortBy çiftinin ilk değeri ve zip tekrar sıralama anahtarını döndürmek için lodash kullanın.

Sıralama değeri çifti çifti dizinini 0 yerine 1 olarak değiştirmek istiyorsanız

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

resim açıklamasını buraya girin


Düzenleme bağlantısını kullanarak bu kodun nasıl çalıştığını açıklayın ve sadece kodu vermeyin, çünkü bir açıklama gelecekteki okuyuculara yardımcı olma olasılığı daha yüksektir. Ayrıca bkz . Nasıl Cevap Verilir . kaynağı
Jed Fox

3

Referansları korurken anahtarları yinelemeli olarak sıralar.

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

Misal:

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}

Güzel pasaj! Orada amaç ne delete o[e[0]];? Sadece atayamaz mıyız?
Boyang

Görünüşe göre, sadece var olmayan anahtarlara yeni atamalar anahtarın sonuna eklenecektir. Silme yorumlanırsa, anahtarlar sıralanmaz, en azından Chrome'da sıralanmaz.
brunettdan

mantıklı. Teşekkürler! Her durumda, js nesne anahtarlarının özelliklerine göre dizisi olmadığı için bu bir tür kayıp nedendir. Sadece obj ve log fonksiyon impl detaylarını kullanıyoruz
Boyang

Evet, anahtar sırası önemli olduğunda Harita kullanıyorum: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
brunettdan

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

3

Bu JSON sıralama için ihtiyacım olan her şeye hafif bir çözümdür.

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

İç içe nesneleriniz varsa veya iç içe dizi obj'niz varsa bu kodu kullanın.

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
Yazar jQuery kullandığını veya jQuery etiketli soruyu belirtmez. Saf javascript'te bir çözüm eklerseniz iyi olur.
rusmus

Teşekkürler @Phani bu tam olarak ihtiyacım olan şey
Will Sheppard

2

Çözüm:

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

Açıklama:

Birçok JavaScript çalışma zamanı, değerleri bir nesnenin içine eklendiği sırayla depolar.

Bir nesnenin özelliklerini anahtarlarına göre sıralamak için, bir anahtar dizisi döndürecek Object.keys işlevini kullanabilirsiniz . Anahtar dizisi daha sonra bir dizinin öğelerini yerinde sıralayan Array.prototype.sort () yöntemine göre sıralanabilir ( bunları yeni bir değişkene atamanıza gerek yoktur).

Anahtarlar sıralandıktan sonra, yeni bir nesneyi (şimdi sıralanmıştır) doldurmak için eski nesnenin içeriğine erişmek için bunları tek tek kullanmaya başlayabilirsiniz.

Aşağıda yordama bir örnek verilmiştir (hedeflediğiniz tarayıcılarda test edebilirsiniz):

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

Not: Object.keys bir ECMAScript 5.1 yöntemidir, ancak eski tarayıcılar için bir çoklu dolgu vardır :

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

Bazı Java numaralarını javascript nesnelerine aktardım.

Bu nesneler benim için doğru diziler döndürdü. nesne anahtarları karışık türdeyse (dize, int, karakter) bir sorun vardır.

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

Lodash kullanarak basit ve okunabilir snippet.

Anahtarı sadece sortBy'yi çağırırken tırnak içine almanız gerekir. Verilerin kendisinde alıntı yapmak zorunda değildir.

_.sortBy(myObj, "key")

Ayrıca, eşlenecek ikinci parametreniz yanlış. Bir işlev olmalı, ancak koparma kullanmak daha kolaydır.

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

2

@Sindresorhus tarafından harika çalışan sıralama anahtarları adı verilen harika bir proje var.

Kaynak kodunu buradan kontrol edebilirsiniz:

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

Veya npm ile kullanabilirsiniz:

$ npm install --save sort-keys

İşte ayrıca benioku kod örnekleri

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

Bir Nesneyi sıralamak için saf JavaScript yanıtı. Negatif sayıları ele alacağını bildiğim tek cevap bu. Bu işlev sayısal Nesneleri sıralamak içindir.

Obj = {1000: {}, -1200: {}, 10000: {}, 200: {}} girin;

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

Çıktı, 0'dan başlayan yeni tuşlarla bu sayılara göre sıralanmış bir nesne olacaktır.


1

Sadece basitleştirmek ve Matt Ball'un cevabını daha net hale getirmek için

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

Bunun soruyu cevaplayıp yanıtlamadığından emin değilim, ama buna ihtiyacım vardı.

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

Olarak adlandırılan :

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

1

Bir satır:

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

1

bunu yapmanın en iyi yolu

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

Neredeyse diziye benzer bir nesneyi gerçek bir diziye dönüştürebilir ve sonra .reverse () kullanabilirsiniz:

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

İlk dizininiz 0 yerine 1 olduğu için sondaki boş yuva .length-- veya .pop () ile boş alanı kaldırabilirsiniz.

Alternatif olarak, .reverse ödünç almak ve aynı nesne üzerinde çağırmak istiyorsanız, tam diziye benzer bir nesne olmalıdır. Yani, length özelliğine ihtiyacı vardır:

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

Aynı tam dizi benzeri nesne nesnesini döndüreceğini unutmayın, bu yüzden gerçek bir dizi olmayacaktır. Daha sonra length özelliğini kaldırmak için delete komutunu kullanabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.