0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScriptのソート備忘録

Posted at

JavaScriptのソート処理

JavaScriptのソート処理するなら、必ずArray.prototype.sort()を使うだろう。
JavaScriptに限らず、たいていのプログラミング言語にはこれに類似するソート処理を実行できるメソッドが用意されているが、仕事でちょっとしたミスプログラムを発見して見逃していたので、今後のために備忘録として残しておくことにする。

備忘録1: ソート前の配列がin placeでソートされる

ソートされた配列が返却されるが、ソート前の配列もソートされた状態になっている(in place)ため、戻り値を再代入しなくてよい。
というか、再代入すると静的解析ツールなどが警告してくることがある。
戻り値はメソッドチェインするときくらいしか意識しなくてよいだろう。

let list1 = [4, 2, 3, 1, 5];
list1.sort();
console.log(list1); // [1, 2, 3, 4, 5]

let list2 = ['a', '', 'bbb', 'A', 'z'];
list2.sort();
console.log(list2); // ["", "A", "a", "bbb", "z"]

備忘録2: 昇順にしたいなら a<b で -1 を!

ソートしたい配列の要素がオブジェクトなど構造を持っているときは、並び順を教えるためのコールバック関数を引数に指定するわけだが、このコールバック関数の戻り値が「昇順の場合は1 なのか -1なのか」といつも忘れるので備忘録に残す。

let list = [4, 2, 3, 1, 5];
list.sort((a, b) => {
  return (a < b) ? -1 : 1; // 昇順ソートの場合はこれ!!
  // return a - b; // これでもいい
});
console.log(list); // [1, 2, 3, 4, 5]

備忘録3: 複数条件でソート

たとえば、以下のように「入社年度」と「社員名」の2つのキーを持つオブジェクトの配列を「まず入社年度で昇順に並べ、同じなら社員名で昇順に並べたい」というような、カテゴリの概念を持ったオブジェクトの配列を複数条件でソートしたいときがある。

ソート前

入社年度 社員名
2020 社員A
2019 社員B
2020 社員C
2019 社員D

ソート後

入社年度 社員名
2019 社員B
2019 社員D
2020 社員A
2020 社員C

このような場合は、まずカテゴリを優先して比較し、カテゴリが同一の場合のみ次の条件で比較することで対応できる。

let list = [{
  item: 2,
  category: 2,
}, {
  item: 1,
  category: 1,
}, {
  item: 4,
  category: 2,
}, {
  item: 3,
  category: 1,
}];

list.sort((a, b) => {
  if (a.category < b.category) {
    return -1;
  } else if (a.category > b.category) {
    return 1;
  } else if (a.item < b.item) {
    return -1;
  } else if (a.item > b.item) {
    return 1;
  }
  return 0;
});

console.log(list);
結果
[{
  category: 1,
  item: 1
}, {
  category: 1,
  item: 3
}, {
  category: 2,
  item: 2
}, {
  category: 2,
  item: 4
}]

これを覚えておけば、サブカテゴリーが増えても対応できるはず。

おまけ

複数条件でソートするVuejsの検証コード抜粋(vue-property-decorator使用)

<table>
  <tbody>
    <tr>
      <th @click="sortList">カテゴリ名</th>
      <th @click="sortList">項目名</th>
    </tr>
    <tr v-for="(item, i) in itemList" :key="i">
      <td :style="item.categoryStyle">{{ item.category }}</td>
      <td :style="item.itemStyle">{{ item.item }}</td>
    </tr>
  </tbody>
</table>
public itemList = [];

public sortList() {
  this.itemList.sort((a, b) => {
    if (a.category < b.category) {
      return -1;
    } else if (a.category > b.category) {
      return 1;
    } else if (a.item < b.item) {
      return -1;
    } else if (a.item > b.item) {
      return 1;
    }
    return 0;
  });
}

/** 乱数取得 */
private getRandomInt(min: number, max: number): number {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min;
}

public created() {
  // 乱数でデータ作成
  for (let i = 0; i < 100; i++) {
    const c = this.getRandomInt(1, 10);
    const s = this.getRandomInt(1, 100);
    this.itemList.push({
      item: s,
      itemStyle: `color:white;background:rgb(0,0,${255 - s * 2})`,
      category: c,
      categoryStyle: `color:white;background:rgb(0,${255 - c * 10},0)`,
    });
  }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?