artwork

JavaScriptで要素が数値である配列をソートするにはArray.sort()を用いれば実現できますが、要素がオブジェクトの配列に対してソートする方法がパッと思いつきませんでした。

要素がオブジェクトの配列とは、次のようなものです。

要素がオブジェクトの配列の例
var arr = [
  {date : '2020-02-20', memo : 'あいうえお'}
, {date : '2020-02-30', memo : 'かきくけこ'}
, {date : '2020-02-10', memo : 'さしすせそ'}
, {date : '2020-02-05', memo : 'たちつてと'}
];

これを並び替えて、

[ {date : '2020-02-05', memo : 'たちつてと'}
, {date : '2020-02-10', memo : 'さしすせそ'}
, {date : '2020-02-20', memo : 'あいうえお'}
, {date : '2020-02-30', memo : 'かきくけこ'}
]

のように、 キー=dateの値を元に昇順(または降順)に並べ替えをした配列を求めたかったのですが、 「どうやるんだっけ?」とすぐには思いつきませんでした。

そこで今回は、JavaScriptで要素がオブジェクトの配列に対してソートする方法をご紹介します。配列+オブジェクトはJavaScriptを扱う上では必須といっていいほどよく使うものだと思いますので、ソートについても是非押さえておきましょう!

オブジェクトの中に配列があるようなケースでも対応できます。

配列内の要素が値の場合のソート方法

まずはじめに、要素が値(オブジェクト以外)の場合のソート方法を振り返ります。

この場合、次のようなコードを書くと配列内の要素をソートすることができます。

var str = ['1', '3', '-1', '2', '5'];
str.sort();
console.log(str);

結果は

["-1", "1", "2", "3", "5"]

となりますので、簡単に昇順に並び順を変えることができます。

逆に降順に並び替える場合、sort関数内で比較用の関数を実行します。

var str = ['1', '3', '-1', '2', '5'];
str.sort(function(a, b) {
   return b - a;
});
console.log(str);

結果は

["5", "3", "2", "1", "-1"]

となり、要素が降順で並び替えされたことが確認できました

補足

昇順に並び替える場合、次のようにしても可能です。

var str = ['1', '3', '-1', '2', '5'];
str.sort(function(a, b) {
   return a - b;    //a-bは昇順、b-aは降順となる
});
console.log(str);

sort内の関数で、a - bを返せば昇順に、b - aを返せば降順に並び替えされます。

配列内の要素がオブジェクトの場合のソート方法

配列内の要素がオブジェクトの場合も、要素が値の場合と基本的に考え方は同じです。

オブジェクト内のあるキーの値でソートする場合

まず昇順で並び替えを行う場合です。

var arr = [
  {date : '2020-02-20', memo : 'あいうえお'}
, {date : '2020-02-30', memo : 'かきくけこ'}
, {date : '2020-02-10', memo : 'さしすせそ'}
, {date : '2020-02-05', memo : 'たちつてと'}
];

という配列を、キー=dateに設定されている値(日付)を元に並び替える場合、次のようなコードで可能です。

var arr = [
  {date : '2020-02-20', memo : 'あいうえお'}
, {date : '2020-02-30', memo : 'かきくけこ'}
, {date : '2020-02-10', memo : 'さしすせそ'}
, {date : '2020-02-05', memo : 'たちつてと'}
];
arr.sort(function(a, b) {
   if (a.date < b.date) {
       return -1;
   } else {
       return 1;
   }
});
console.log(arr);

結果は次のようになり、

要素がオブジェクトの配列を昇順ソートした結果

キー;dateの値(日付)の昇順で配列の要素がソートされました。

ポイント

sort関数内で、ソート時の条件にしたいフィールドで判定を行う。

逆に降順でソートする場合、sort()内で呼び出している関数の不等号を逆にすればよいです。

var arr = [
  {date : '2020-02-20', memo : 'あいうえお'}
, {date : '2020-02-30', memo : 'かきくけこ'}
, {date : '2020-02-10', memo : 'さしすせそ'}
, {date : '2020-02-05', memo : 'たちつてと'}
];
arr.sort(function(a, b) {
   if (a.date > b.date) {
       return -1;
   } else {
       return 1;
   }
});
console.log(arr);

結果は次のように、キー:dateの値で降順に並び替えされた結果の配列となります。

要素がオブジェクトの配列を降順ソートした結果

オブジェクト内のあるキーでソートする場合

今度は、オブジェクト内のキーを条件にソートする場合です。

例えば次のように、キー(以下で言うと日付部分)に対して配列の並び替えをしたいケースが該当します。

var arr = [
  {'2020-02-20' : {aaa : 1, memo : 'あいうえお'}}
, {'2020-02-30' : {aaa : 2, memo : 'かきくけこ'}}
, {'2020-02-10' : {aaa : 3, memo : 'さしすせそ'}}
, {'2020-02-05' : {aaa : 4, memo : 'たちつてと'}}
];

これもこれまでと同じ考え方をすればよいです。sort()内で並びの判定をする部分を、オブジェクトキーを元に判定する形に変更すれば実現できます。

var arr = [
  {'2020-02-20' : {aaa : 1, memo : 'あいうえお'}}
, {'2020-02-30' : {aaa : 2, memo : 'かきくけこ'}}
, {'2020-02-10' : {aaa : 3, memo : 'さしすせそ'}}
, {'2020-02-05' : {aaa : 4, memo : 'たちつてと'}}
];
arr.sort(function(a, b) {
   if (Object.keys(a) < Object.keys(b)) {
       return -1;
   } else {
       return 1;
   }
});
console.log(arr);

実行した結果は次のようになり、ソート時のキーとした日付で配列が並び替えされているのが確認できました。

要素がオブジェクトの配列をオブジェクトキーで昇順ソートした結果

降順に並び替える場合はsort関数内の不等号を逆にすればよいだけです。

var arr = [
  {'2020-02-20' : {aaa : 1, memo : 'あいうえお'}}
, {'2020-02-30' : {aaa : 2, memo : 'かきくけこ'}}
, {'2020-02-10' : {aaa : 3, memo : 'さしすせそ'}}
, {'2020-02-05' : {aaa : 4, memo : 'たちつてと'}}
];
arr.sort(function(a, b) {
   if (Object.keys(a) > Object.keys(b)) {
       return -1;
   } else {
       return 1;
   }
});
console.log(arr);

ネストが深いオブジェクトの場合のソート応用例

配列内のオブジェクトのネストが深く、これまでのように単純にはいかなそうな場合にどうやるかを最後にご紹介します。

例えば、次のように、オブジェクトの中にある配列内に対して日付でソートしたい場合です。

var record = {
  Table : { 
    value : [
      {value : 
        {lang  : {value : 'JavaScript'}
        ,skill : {value : 'A'}
        ,date  : {value : '2020-02-13'}
        }
      }
    , {value : 
        {lang  : {value : 'C++'}
        ,skill : {value : 'B'}
        ,date  : {value : '2020-02-02'}
        }
      }
    , {value : 
        {lang  : {value : 'TypeScript'}
        ,skill : {value : 'C'}
        ,date  : {value : '2020-02-30'}
        }
      }
    , {value : 
        {lang  : {value : 'VBA'}
        ,skill : {value : 'S'}
        ,date  : {value : '2020-02-10'}
        }
      }
    ] 
  }
};

階層的に表現するとこんなオブジェクトです。

このオブジェクト内の配列をソートする場合は、こんなコードで実現可能です。

var record = {
  Table : { 
    value : [
      {value : 
        {lang  : {value : 'JavaScript'}
        ,skill : {value : 'A'}
        ,date  : {value : '2020-02-13'}
        }
      }
    , {value : 
        {lang  : {value : 'C++'}
        ,skill : {value : 'B'}
        ,date  : {value : '2020-02-02'}
        }
      }
    , {value : 
        {lang  : {value : 'TypeScript'}
        ,skill : {value : 'C'}
        ,date  : {value : '2020-02-30'}
        }
      }
    , {value : 
        {lang  : {value : 'VBA'}
        ,skill : {value : 'S'}
        ,date  : {value : '2020-02-10'}
        }
      }
    ] 
  }
};
var tmp = record['Table']['value'].map(function(rec) {
             return {
               rec  : rec
             , key : rec['value']['date']['value'] 
             };
         }).sort(function(a, b){    
             if (a.key < b.key) {   //昇順ソート
               return -1;
             } else {
               return 1;
             }
         }).map(function(obj) {
             return obj.rec;
         });
console.log(tmp);

結果は次のようになり、オブジェクト内の配列が日付ごとに昇順に並び替えすることができました。

あとは変数tmpに格納されている配列を元のオブジェクトにセットしてあげれば、オブジェクトとしても内部の配列が並び替えられたものを保持することができます。

まとめ

今回は、JavaScriptで要素がオブジェクトの配列に対してソートする方法をご紹介しました。

配列をソートしたいケースは結構ありますが、ここにオブジェクトも絡んでくると中々すぐにはコードが思い浮かびません。

そのような時に本記事を参考にしてみてくださいね!(もっと良い実現方法があれば、コメント欄で教えてください)

Twitterでフォローしよう

おすすめの記事