JavaScriptオブジェクトをキーでソート


532

JavaScriptオブジェクトをキーでソートする必要があります。

したがって、次のようになります。

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

になるでしょう:

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


39
2011年に(この質問が投稿されたとき)、ECMAScriptの仕様では、JavaScriptオブジェクトには固有の順序はありません。観察された順序は実装に依存しているため、信頼できませんでした。ただし、すべてのJavaScriptエンジンがほぼ同じセマンティクスを実装ていることが判明したため、これらのエンジンはES6で標準化されました。その結果、以下の回答の多くは以前は仕様に従って正しいものでしたが、現在は正しくありません。
Mathias Bynens、2015年

結果を比較またはハッシュする必要がある場合は、ソートされたstringifyを
exebook

オブジェクトが単なるマップ、または言語に応じてディクテーションであることを考えると、これを行う理由はほとんどありません。これは、一般に、マップに挿入される順序が、実際には文字列化するときに存在する順序です。SO、新しいマップを作成し、事前にソートされたキーリストに基づいて値を割り当てた場合、キーに基づいて順序付けられたマップが見つかります
Fallenreaper

以来、ことを注意Object.entriesしてObject.fromEntriesJSに追加された、これはうまく短いワンライナーで達成することができる:Object.fromEntries(Object.entries(obj).sort())
マイクのPomax時"Kamermans

回答:


471

この質問に対する他の回答は古くなっており、実装の現実とは一致しておらず、ES6 / ES2015仕様が公開されたため、正式には正しくありません。


参照してください上のセクションのプロパティ繰り返し順序をES6を探るアクセルRauschmayerによって

プロパティキーを反復するすべてのメソッドは、同じ順序でこれを行います。

  1. 最初に、数値でソートされたすべての配列インデックス。
  2. 次に、すべての文字列キー(インデックスではない)が作成された順序で。
  3. 次に、すべてのシンボルが作成された順序で表示されます。

つまり、JavaScriptオブジェクト実際には順序付けられており、それらのキー/プロパティの順序は変更できます。

キー/プロパティでオブジェクトをアルファベット順に並べ替える方法は次のとおりです。

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

var代わりにconstES5エンジンとの互換性のために使用します。


5
わずかに異なるループテクニックを使用する以外は、コードとここでのトップアンサーの違いは本当にわかりません。オブジェクトが「順序付けられている」と言えるかどうかは無関係です。この質問への答えはまだ同じです。公開された仕様は、ここで答えを確認するだけです。
Phil

6
FYI、次のことが明らかになった列挙プロパティの順序がまだ定義されていない:esdiscuss.org/topic/...
フェリックスクリング

6
@ Phil_1984_この回答と上位投票の回答は大きく異なります。OPの質問は、オブジェクトリテラルを並べ替える方法でした。上位の投票された回答ではできないと答え、並べ替えられたキーを配列に格納し、並べ替えられた配列からキーと値のペアを繰り返し出力することで回避策を提供しています。この回答は、オブジェクトリテラルの順序がソート可能になり、彼の例はソートされたキー値をオブジェクトリテラルに格納し直して、ソートされたオブジェクトを直接出力すると主張しています。余談ですが、リンクされたサイトがまだ存在しているとよいでしょう。
チェンバレン2016年

6
どちらの答えも、単にArray.sort関数を使用して、キーを最初にソートします。OPは「JavaScriptオブジェクト」のソートを要求しており、2つのオブジェクトを記述するためにJavaScript Object Notation(JSON)を単に使用しています。これらの2つのオブジェクトは論理的に同一であり、ソートは無関係です。一番上の答えはこれをもっとよく説明していると思います。「他のすべての回答は現在公式に正しくない」と言うことは、特にリンクが壊れている場合、私にとっては極端すぎます。問題は、「この新しいES6仕様」が、JavaScriptオブジェクトにキーの順序付けられたリストがあるという幻想を与えていることだと思います。
Phil

1
このソリューションは、さまざまな最新のブラウザ(google "caniuse ES6")ではサポートされていないことを付け加えてください。この回答を使用すると、特定のブラウザのみでバグを見つけるのが難しくなります(たとえば、Chromeがすべて正常な場合のSafari)。
Manuel Arwed Schmidt 2016

244

JavaScriptオブジェクト1は順序付けされていません。それらを「ソート」しようとしても意味がありません。オブジェクトのプロパティを反復処理する場合は、キーを並べ替えて、関連する値を取得できます。

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.keys空想を使用した代替実装:

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面倒ではありませんが、JSONオブジェクトなどはありません。


2
@MarcelKorpel JSONオブジェクトのようなものがあります。公式JSON RFCのセクション8を確認してください:ietf.org/rfc/rfc4627.txt
Paul

8
@PaulproはそのRFCについて2つの注意点があります。1つ目は、現時点で7歳であり、語彙は時間とともに変化します。第二に、「このメモはインターネットコミュニティに情報を提供します。いかなる種類のインターネット標準も指定していません。」特定の文字シーケンスがJavaScriptオブジェクトリテラルを表すかJSONテキストを表すかは、コンテキスト/使用法によって異なります。「JSONオブジェクト」という用語は、有害な方法で区別をあいまいにし、あいまいにします。不正確な用語を取り除き、可能な場合はより正確な用語を使用してみましょう。そうでなければ理由はない。言葉は重要です。
マットボール

6
@MattBall IMO JSONオブジェクトは、{"a", 1}JSON配列がのような文字列の正確な用語であるのと同様に、文字列の非常に正確な用語です[1]。文字列があるときに、配列の3番目のオブジェクトなどを言って通信できると便利です[{x: 1}, {y: 2}, {z: 3}]。そのため、Javascriptリテラルについてコメントするときは、「そのようなものはありません」ではなく、「JSONオブジェクトではない」ことを好みます。これは、OPが実際にJSONを処理しているときに、混乱と通信の問題を引き起こすだけです。
Paul

3
@Paulpro同意しないでください。{"a", 1}オブジェクトリテラルまたはJSONテキスト(JSON文字列、別名)。どちらがコンテキストに依存するか、前者がJavaScriptソースコード内でそのまま表示される場合、後者は、さらに使用するためにJSONパーサーに渡す必要がある文字列である場合。許可された構文、正しい使用法、およびシリアル化に関しては、2つの間に実際の違いがあります。
マットボール

4
ES6 / ES2015が確定したので、この回答は正式に正しくありません。詳細については、私の回答を参照してください。
Mathias Bynens、2015年

172

多くの人が「オブジェクトはソートできない」と述べていますが、その後、彼らはあなたに機能する解決策を提供しています。パラドックスですね。

これらのソリューションが機能する理由については誰も言及していません。ほとんどのブラウザの実装では、オブジェクトの値は追加された順序で格納されるためです。そのため、キーの並べ替えられたリストから新しいオブジェクトを作成すると、予期した結果が返されます。

そして、もう1つのソリューション、ES5の機能的な方法を追加できると思います。

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

上記のES2015バージョン(「ワンライナー」形式):

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

上記の例の簡単な説明(コメントで尋ねられたとおり):

Object.keys提供されたオブジェクト(objまたはo)のキーのリストを提供している場合、デフォルトのソートアルゴリズムを使用してそれらをソートします。次に.reduce、その配列をオブジェクトに変換するために使用されますが、今回はすべてのキーがソートされています。


7
@Pointyこの動作は、すべての主要なブラウザーで常に使用可能であり、ES6 / ES2015で標準化されています。これは良いアドバイスだと思います。
Mathias Bynens、2015年

3
これは、EcmaScript v5でタスクを実行する最も簡単で最も簡潔な方法です。パーティーには少し遅れますが、受け入れられるべき答えです。
Steven de Salas、2015

2
「そうです。ほとんどのブラウザの実装では、オブジェクトの値はそれらが追加された順序で格納されているためです」ただし、非数値プロパティの場合のみ。また、プロパティが(たとえばを介してfor...in)繰り返される保証はないことに注意してください。
Felix Kling 2016

2
なぜそれが機能しているのか説明してくれてありがとう。ありがとう!
ola

5
私のリンターはその1行(課題を返す)について不平を言っていましたが、これは私にとってはObject.keys(dict).sort().reduce((r, k) => Object.assign(r, { [k]: dict[k] }), {});
うまくいき

68

私は比喩的にショックを受けています!確かにすべての回答は少し古いですが、ソートの安定性については誰も言及していません!だから私と一緒に耐えてください、私は質問自体に答えて、ここで詳細に入るように最善を尽くします。大変お詫び申し上げます。

2018年なので、ES6のみを使用します。ポリフィルはすべて、MDNのドキュメントで入手できます。MDNのドキュメントは、所定の部分でリンクします。


質問への回答:

キーが数値のみの場合、とObject.keys()一緒に安全に使用して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), {}));

ただし、文字列を使用している場合はArray.prototype.sort()、このすべてにチェーンすることを強くお勧めします。

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

誰かが削減が何をするのか疑問に思っている場合:

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

必要に応じて、ここに1つのライナーの説明を示します。

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

並べ替えが少し複雑な理由:

つまりObject.keys()、通常のループで取得したのと同じ順序の配列を返します。

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

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

Object.keys()は、要素がオブジェクトに直接ある列挙可能なプロパティに対応する文字列である配列を返します。プロパティの順序は、オブジェクトのプロパティを手動でループする場合と同じです。

サイドノート- Object.keys()配列でも使用できます。インデックスが返されることに注意してください。

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

しかし、これらの例に示すほど簡単ではありません。実際のオブジェクトには、数字やアルファベット文字、さらには記号が含まれている場合があります(実行しないでください)。

これらはすべて1つのオブジェクトにある例です。

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

ここArray.prototype.sort()で、上記の配列で出力を変更すると、次のようになります。

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

これはドキュメントからの引用です:

sort()メソッドは、配列の要素を所定の位置にソートし、配列を返します。ソートは必ずしも安定しているとは限りません。デフォルトのソート順は、文字列のUnicodeコードポイントに従います。

ソートの時間とスペースの複雑さは、実装に依存するため保証できません。

それらの1つが目的の出力を返すことを確認する必要があります。実際の例では、APIやデータベースなどの異なる情報入力を一緒に使用すると、人々は物事を特別に混同する傾向があります。


だから大したことは何ですか?

さて、すべてのプログラマが理解すべき2つの記事があります。

インプレースアルゴリズム

コンピュータサイエンスでは、インプレースアルゴリズムは、補助データ構造を使用せずに入力を変換するアルゴリズムです。ただし、補助変数用に少量の追加のストレージスペースが許可されています。アルゴリズムが実行されると、通常、入力は出力によって上書きされます。インプレースアルゴリズムは、要素の置換または交換によってのみ入力シーケンスを更新します。インプレースではないアルゴリズムは、インプレースまたはアウトオブプレースと呼ばれることもあります。

したがって、基本的には古い配列が上書きされます!他の理由で古いアレイを保持したい場合、これは重要です。これを覚えておいてください。

並べ替えアルゴリズム

安定したソートアルゴリズムは、入力に現れるのと同じ順序で同一の要素をソートします。一部の種類のデータを並べ替える場合、並べ替え順序を決定するときにデータの一部のみが検査されます。たとえば、右側のカードソートの例では、カードはランクでソートされており、スートは無視されています。これにより、元のリストの複数の異なる正しくソートされたバージョンの可能性が可能になります。安定した並べ替えアルゴリズムは、次のルールに従ってこれらのいずれかを選択します。2つの5つのカードのように2つのアイテムが等しいと比較した場合、それらの相対的な順序は保持されるため、入力で一方が他方の前に来た場合も、出力で他の前に来る。

ここに画像の説明を入力してください

トランプの安定したソートの例。カードが安定したソートでランクによってソートされる場合、2つの5は、元々あったソートされた出力で同じ順序のままである必要があります。非安定なソートでソートされた場合、5は逆になります。ソートされた出力の順序。

これは、ソートが正しいことを示していますが、変更されています。したがって、現実の世界では、並べ替えが正しい場合でも、期待どおりの結果が得られることを確認する必要があります。これは非常に重要であり、これも覚えておいてください。その他のJavaScriptの例については、Array.prototype.sort()を調べてください -ドキュメント:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort


3
あなたは岩盤を弾く、この信じられないほどの答えをありがとう。SOで私が見た中で最高の1つ。乾杯。
ギャビン

最後に使用するおかしな方法を提供できたとしたら。素晴らしい答えです!
mmm '27年

@momomo問題は、ソートに何を期待するかによって、正しい方法がないことです。しかし、あなたは私の答えからこのコードを使用することができます:Object.keys(testObj).sort().reduce((a, c) => (a[c] = testObj[c], a), {})
メガジン

並べ替えの安定性はこの質問には適用されませんか。オブジェクトキーで並べ替えており、キーは一意です。(お使いのカードの例を拡張するには:彼らは異なるスーツである場合でも、パックに2つの5Sがなることはありません。)
ダレン・クック

@DarrenCookいい質問です!1つのオブジェクトに同じキーが存在することはありません。ただし、安定性はキーの一意性よりも複雑です。ほとんどの場合、配列はオブジェクトのソートに含まれます。そして、それはすべてが不安定になる可能性があるときです。5人のプレイヤーが参加するカードゲームを想像してみてください。各手は、配列(個々の手による並べ替えを維持するため)とカードをオブジェクトとして表します。カードがこのように見える場合、{5: 'hearts'}または{5: 'spades'}配列のソートを開始すると、ラミーのようなゲームでは潜在的に不安定になります。異なる言語について話さないこと。
メガジン

29

これは私のために働く

/**
 * 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
これは、実際の質問に対する正解です。アンダースコアを使用した簡易版は、以下を参照してくださいjsfiddle.net/wPjaQ/1
被平方根

6
@radicandいいえこの答えは不正解です。これも新しいオブジェクトを返しますが、これにも順序はありません。
ポール・

3
@radicand実際にはありません。オブジェクトのキーには順序というものはありません。そのため、実際にはオブジェクトがソートされた順序であると言えるのでしょうか。それは本当にちょうどあなたが渡したオブジェクトの簡易コピーをバックアップできます。
ポール・

9
これは間違いです。今のところうまくいくかもしれませんが、同じブラウザーで別のWebブラウザーまたは別のページの読み込みで中断します。ブラウザは、セキュリティのためにオブジェクトキーをランダム化する場合があります。または、オブジェクトを埋めるときに、キーに応じて異なるメモリバケットに値を入れ、異なる順序を返します。これが機能する場合、それはあなたにとって幸運です。
Yobert

11
また、jQueryを不必要に使用します。
RobG 2014

25

それは2019年であり、これを解決するための2019年の方法があります:)

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

2
ネストされたオブジェクトをキーでどのようにソートしますか?
a2441918

@ a2441918 sort()関数で行うのと同じ方法で。見てください: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ユーザーの場合、これはまだ使用できません。github.com
microsoft

素敵なワンライナーですが、大文字と小文字を区別しない方法でキーを並べ替える方法は?
theMaxx

1
@theMaxx次のようなカスタム関数をソートに使用します: `` `Object.fromEntries(Object.entries({b:3、a:8、c:1})。sort(([key1、val1]、[key2、 val2])=> key1.toLowerCase()。localeCompare(key2.toLowerCase()))) `` `
Ben

22

こちらは1ライナーです

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


このクレイジーな構文は一体何ですか?(o[k] = v, o)。なぜこれでも機能するのですか?それに関するドキュメントはどこにありますか?明らかに一番右のパラメータを返しますが、なぜですか?
ntaso

1
@ntaso here
James

短い関数は最初にをo[k]等しくしvてから返しますo
Tahsin Turkoz

19

これは古い質問ですが、Mathias Bynensの答えからヒントを得て、現在のオブジェクトをソートする短いバージョンを作成しましたが、オーバーヘッドはそれほどありませんでした。

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

コードの実行後、「順序付けられていない」オブジェクト自体にキーがアルファベット順にソートされます。


17

lodashを使うとこれはうまくいきます:

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

ただ考えるための食べ物。


15

順序付けられていないオブジェクトプロパティを表示するVisualStudioデバッガーで役立つと仮定します。

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

とても素晴らしいおかげloooot
麦わら

いいね!この簡潔な解決策をありがとう。
Con Antonakos、2015年

9

下線バージョン

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

ブラウザーがキーの順序を維持することを信頼していない場合は、キーと値のペア配列の順序付けされた配列に依存することを強くお勧めします。

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

より良い:_.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,
});

多分あなたのコードのいくつかの説明を追加する方が良いでしょう。
aristotll 2017

1
オブジェクトのキーを取得するので、それは文字列の配列なので、それらをsort()し、文字列(キー)の配列なので、(js配列のreduce()を使用して)削減します。accは最初は空のオブジェクト{}(レデューサーの最後の引数)であり、レデューサー(コールバック)は空のオブジェクトに、順序付けられたキーシーケンスを持つソースobjの値を割り当てます。
user3286817

8

多分もう少しエレガントな形:

 /**
     * 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およびES6 +構文と同じ:

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

それは何もソートしません。あなたはまだオブジェクトを返します。ターゲット内のオブジェクトが実際に順序を持つことを保証することはできません。配列を返す必要があります。ジーズー。
mmm

ここで行うのは、最適でない方法でセットであることを確認することだけです。
mmm '27年

7

ネストされたオブジェクトと配列の再帰的ソート

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

私はあなたが必要だと思うelseそこに-両方のための真の可能性Array.isArray(obj[key])とのためにtypeof obj[key] === 'object'
jononomo

プリミティブの配列がある場合、関数はプリミティブ(文字列/数値)を空のオブジェクトに変換します。これをキャッチするために、関数の先頭に次の権利を追加しましたfunction sortObjectKeys(obj){::if(typeof obj != 'object'){ /* it is a primitive: number/string (in an array) */ return obj; }。堅牢性のために、完全な開始時にIも追加されましたif(obj == null || obj == undefined){ return obj; }
。–

4

すでに述べたように、オブジェクトは順序付けされていません。

しかしながら...

あなたはこのイディオムが役に立つかもしれません:

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

var kv = [];

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

kv.sort()

その後、kvを反復処理して、好きなように実行できます。

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


4

ネストされたオブジェクトで機能する、きれいなlodashベースのバージョンは次のとおりです

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

ロダッシュにtoObject()メソッドがあったらもっときれいになるだろう...


3

lodashを使用してマップを解凍し、ペアの最初の値であるsortByをもう一度圧縮して、ソートされたキーを返します。

sortby値が必要な場合は、ペアのインデックスを0ではなく1に変更します

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

ここに画像の説明を入力してください


編集リンクを使用して、このコードがどのように機能するかを説明してください。説明は将来の読者を助ける可能性が高いので、コードを提供するだけではありません。回答方法もご覧ください。出典
Jed Fox、

3

参照を保持しながら、キーを再帰的にソートします。

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

例:

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}

いいスニペット!delete o[e[0]];そこの目的は何ですか?ただ割り当てることはできませんか?
ボヤン、

存在しないキーへの新しい割り当てだけが最後にキーを追加するようです。削除がコメント化されている場合、少なくともChromeではキーはソートされません。
brunettdan '20年

それは理にかなっている。ありがとう!いずれにせよ、仕様によると、jsオブジェクトキーにはシーケンスがないため、これは一種の失われた原因です。私たちはobjとlog関数の実装の詳細を利用しています
Boyang

キーの順序が重要な場合にいや、私は地図を使用します。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
brunettdan


3

これは、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

オブジェクトをネストしている場合、または配列objをネストしている場合は、このコードを使用します。

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
著者は、jQueryを使用していると述べておらず、質問にjQueryのタグが付けられていません。純粋なJavaScriptでソリューションを追加すると便利です。
rusmus 2014

この@Phaniおかげで、私がまさに必要である
ウィル・シェパード

2

解決:

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

説明:

多くのJavaScriptランタイムは、追加された順序でオブジェクト内に値を格納します。

キーでオブジェクトのプロパティをソートするには、キーの配列を返すObject.keys関数を使用できます。キーの配列は、Array.prototype.sort()でソートできます要素をメソッド(新しい要素に割り当てる必要はありません)。

キーがソートされたら、キーを1つずつ使用して、古いオブジェクトのコンテンツにアクセスし、新しいオブジェクト(現在はソートされている)を埋めることができます。

以下は手順の例です(対象のブラウザーでテストできます)。

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

注: Object.keysはECMAScript 5.1メソッドですが、これは古いブラウザーのポリフィルです。

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

いくつかのJava enumをjavascriptオブジェクトに転送しました。

これらのオブジェクトは正しい配列を返しました。オブジェクトキーが混合型(string、int、char)の場合、問題があります。

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を使用したシンプルで読みやすいスニペット。

sortByを呼び出す場合にのみ、キーを引用符で囲む必要があります。データ自体で引用符で囲む必要はありません。

_.sortBy(myObj, "key")

また、マップする2番目のパラメーターが間違っています。それは関数であるべきですが、pluckを使う方が簡単です。

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

2

@sindresorhusによるsort-keysと呼ばれる素晴らしいプロジェクトがあり、これは素晴らしい働きをします。

ここでソースコードを確認できます。

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

または、npmで使用できます。

$ npm install --save sort-keys

ここにも彼のReadmeのコード例があります

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

オブジェクトをソートするための純粋なJavaScript応答。これが、負の数を処理することを知っている唯一の答えです。この関数は、数値オブジェクトをソートするためのものです。

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

出力は、新しいキーが0で始まる数値でソートされたオブジェクトになります。


1

単純化してマットボールからの回答をより明確にする

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

これが質問に答えるかどうかはわかりませんが、これが私が必要としたものです。

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

と呼ばれる:

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

1

1行:

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

1

それを行う最善の方法は

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

まず、ほぼ配列のようなオブジェクトを実際の配列に変換し、次に.reverse()を使用できます。

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

最初のインデックスが0ではなく1であるため、最後の空のスロットが原因です。空のスロットは、.length--または.pop()で削除できます。

または、.reverseを借用して同じオブジェクトで呼び出す場合は、完全に配列のようなオブジェクトでなければなりません。つまり、長さのプロパティが必要です。

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

同じ完全な配列のようなオブジェクトオブジェクトを返すため、実際の配列にはならないことに注意してください。次に、deleteを使用して、lengthプロパティを削除できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.