Array.prototype.sort()メソッドの使い方（備忘録）

# この投稿は
JavaScriptのsort()メソッドの使い方が分からなかったので備忘録としてのメモです。
sort()メソッドを使ったコードを見ると、みんな当たり前のように引数に関数を使っているし、戻り値の訳が分からんし・・・ってことで。

## 基本形
JavaScriptのsort()メソッドは、どうやら「高階関数」ってやつで、引数に関数を指定するっぽい。
[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort "MDN Array.prototype.sort()") によると、引数として設定する関数は以下のようにaとbを引数とした、無名のアロー関数で記述するんだそうだ。（もちろん、別の書き方もあるはず。）
```javascript
const array = []; //配列の宣言

array.sort((a,b) => {
    //関数の中身
});
```
こんな感じかな？
引数aとbは、配列から適当に「要素」を代入してくれるらしい。開発者はaとbを比較とか演算すればいいんだそうだ。

## 戻り値の意味
関数の戻り値が一番意味が分からなかったんだよね。サンプルのプログラムを見るとみんなこんな風に書いてある。
```javascript
array.sort((a,b) => {
    return a-b;
});

```
なんで計算結果を返すといいんだか？　全く分からなかった。
これも、[MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort "MDN Array.prototype.sort()") に書いてあった。
戻り値で要素aとbの並びを変えるらしい。

<table>
  <caption>戻り値とその挙動</caption>
  <thead>
    <tr bgcolor="#ddd">
      <th>戻り値</th>
      <th>挙動</th> <th>要素aとbの位置関係</th>
    </tr>
  </thead>
    <tr>
    <tr>
    <td> ０以上 </td>
    <td>a を b の後ろに並べる</td>
    <td>
        <table>
          <tr><th>並び</th></tr>
          <tr><td>b</td></tr>
          <tr>
          <tr><td>a</td></tr>
        </table>
    </td>
    </tr>
    <tr>
    <tr>
    <td> ０以下 </td>
    <td>b を a の後ろに並べる</td>
    <td>
        <table>
          <tr><th>並び</th></tr>
          <tr><td>a</td></tr>
    <tr>
          <tr><td>b</td></tr>
        </table>
    </td>
    </tr>
    <tr>
    <tr>
    <td> ０ </td>
    <td>何もしない</td>
    <td>元と同じ
    </td>
    </tr>
</table>

なので、戻り値が０以上の時は、並びが逆転するっぽい。
これで、数値を戻り値にする意味がわかった。

## 上記を踏まえて昇順ソート
上記を踏まえて、１次元配列の昇順ソートをするとなると、
```javascript
const array = [4,4,2,3,2,3]; //テスト用に配列に要素を設定

array.sort((a,b) => {
  if (a == b) {
    return 0;
  } else if (a > b) {
    return 1;
  } else {
    return -1;
  }
});
```
のようになる。
ここで、戻すべき戻り値をもう一度見てみよう。
「０以上」「０以下」「０」となっている。
「１」「ー１」「０」ではない。
なので、昇順ソートは以下のようにも書き換えられるみたい。
```javascript
const array = [4,4,2,3,2,3]; //テスト用に配列に要素を設定

array.sort((a,b) => {
  return a - b;
});

```
数値であればこっちの方がすっきりする。

## 降順ソートは？
１次元配列の降順ソートをするとなると、b より a が小さい場合０以上を戻せばいいのだから、
```javascript
const array = [1,4,2,3,2,3]; //テスト用に配列に要素を設定

array.sort((a,b) => {
  if (a == b) {
    return 0;
  } else if (a > b) {
    return -1;
  } else {
    return 1;
  }
});
```

のようになる。また、以下のようにも書き換えられる。
```javascript
const array = [1,4,2,3,2,3]; //テスト用に配列に要素を設定

array.sort((a,b) => {
  return b - a;
});

```

## 二次元配列のソート
### キー１つで昇順の場合
二次元配列を１つのキーでソートする時はこう考えるとよさそう。
二次元配列を表と考えて、引数に渡される要素は「行」部分と考える、また、行の中の「列」を比較するようにする。
こんな感じ。
```javascript
const array = [
  [4,2],
  [4,1],
  [2,2],
  [3,3],
  [2,2],
  [3,5]
]; //テスト用に配列に要素を設定

//aとbには、表でいう行部分（[4,1]とか[2,2]とか・・・）が引き渡される。
array.sort((a,b) => {
  //表でいう列部分を比較する。
  if (a[0] == b[0]) {
    return 0;
  } else if (a[0] > b[0]) { 
    return 1;
  } else {
    return -1;
  }
});
```
また、以下のようにも書き換えられる。

```javascript
const array = [
  [4,2],
  [4,1],
  [2,2],
  [3,3],
  [2,2],
  [3,5]
]; //テスト用に配列に要素を設定

//aとbには、表でいう行部分（[4,1]とか[2,2]とか・・・）が引き渡される。
array.sort((a,b) => {
  //表でいう列部分を演算する。
  return a[0] - b[0];
});
```
### キー２つで昇順の場合

二次元配列を２つのキーでソートする時は、
キー１が同じときだけ、キー２を比較すると良さそうだ。
```javascript
const array = [
  [4,2],
  [4,1],
  [2,2],
  [3,3],
  [2,2],
  [3,5]
]; //テスト用に配列に要素を設定

//aとbには、表でいう行部分（[4,1]とか[2,2]とか・・・）が引き渡される。
array.sort((a,b) => {
  //表でいう列部分（キー１）を比較する。
  if (a[0] == b[0]) {
    //キー１が同じときだけ、キー２を比較する。
    //表でいう列部分（キー２）を比較する。
    if (a[1] == b[1]) {
      //キー１とキー２が同じなら０を戻す。
      return 0;
    } else if (a[1] > b[1]) { 
      return 1;
    } else {
      return -1;
    }
  } else if (a[0] > b[0]) { 
    return 1;
  } else {
    return -1;
  }
});
```
また、以下のようにも書き換えられる。
```javascript
const array = [
  [4,2],
  [4,1],
  [2,2],
  [3,3],
  [2,2],
  [3,5]
]; //テスト用に配列に要素を設定

//aとbには、表でいう行部分（[4,1]とか[2,2]とか・・・）が引き渡される。
array.sort((a,b) => {
  //表でいう列部分（キー１）を比較する。
  if (a[0] == b[0]) {
    //キー１が同じときだけ、表でいう列部分（キー２）を演算する。
    return a[1] - b[1];
  } else {
    //表でいう列部分（キー１）を演算する。
    return a[0] - b[0];
  }
});
```


## オブジェクトのソート
オブジェクト配列の場合は、a や b に引き渡されるものはオブジェクト( **{'v1':4,'v2':4}** など)。
比較はオブジェクトの値を比較すれば良さそう。
```javascript
let array = [
  {'v1':3,'v2':3},
  {'v1':4,'v2':4},
  {'v1':1,'v2':3},
  {'v1':2,'v2':4},
  {'v1':1,'v2':1},
  {'v1':2,'v2':4},
]

//aやbにはオブジェクト({'v1':2,'v2':4}）が引き渡される。
array.sort((a,b) => {
  //オブジェクトの値を比較。
  if (a.v1 == b.v1) {
    return 0;
  } else if (a.v1 > b.v1) {
    return 1; 
  } else {
    return -1;
  }
});
```

これも、次のように書き換えられる。
```javascript
let array = [
  {'v1':3,'v2':3},
  {'v1':4,'v2':4},
  {'v1':1,'v2':3},
  {'v1':2,'v2':4},
  {'v1':1,'v2':1},
  {'v1':2,'v2':4},
]

//aやbにはオブジェクト({'v1':2,'v2':4}）が引き渡される。
array.sort((a,b) => {
  //オブジェクトの値を比較。
  return a.v1 - b.v1; 
});
```

## まとめ
僕なりのまとめ。
* sort()メソッドを使うためには、引数に以下のように a と b を引数とした関数を記載。
* その関数内で、０以上、０以下、０のいずれかを戻す。
* 戻り値が、０以上なら、要素の並びが逆転する。

```javascript
const array = []; //配列の宣言

array.sort((a,b) => {
    //関数の中身
});
```