JSのソート

JSのソート

こんにちは。kyamashitaです。

JSで配列のソート実装した際に、ちょっとハマったので、備忘録として残しておきます。

単純な数値配列

let items = [5,2,3,1,4];

// 昇順
items.sort((a,b) => a < b ? -1 : 1);
> [1, 2, 3, 4, 5]

// 降順
items.sort((a,b) => a < b ? 1 : -1);
> [5, 4, 3, 2, 1]

連想配列でキーを指定する

let items = [
  {"name":"BB", "val":5},
  {"name":"EE", "val":2},
  {"name":"DD", "val":4},
  {"name":"AA", "val":3},
  {"name":"CC", "val":1},
];

// val の 昇順
items.sort((a,b) => a.val < b.val ? -1 : 1);

> 0: {name: "CC", val: 1}
> 1: {name: "EE", val: 2}
> 2: {name: "AA", val: 3}
> 3: {name: "DD", val: 4}
> 4: {name: "BB", val: 5}

// val の 降順
items.sort((a,b) => a.val < b.val ? 1 : -1);

> 0: {name: "BB", val: 5}
> 1: {name: "DD", val: 4}
> 2: {name: "AA", val: 3}
> 3: {name: "EE", val: 2}
> 4: {name: "CC", val: 1}

連想配列でキーを指定する2

valの値が数値、文字列、空文字があり、0が重複している。

このような場合うまくいきません。

let items = [
  {"name":"D", "val":0},
  {"name":"H", "val":"0"},
  {"name":"C", "val":""},
  {"name":"G", "val":""},
  {"name":"B", "val":0},
  {"name":"I", "val":""},
  {"name":"A", "val":"0"},
  {"name":"F", "val":""},
  {"name":"E", "val":0},
];

items.sort((a,b) => a.val < b.val ? -1 : 1);

> 0: {name: "D", val: 0}
> 1: {name: "C", val: ""}
> 2: {name: "G", val: ""}
> 3: {name: "F", val: ""}
> 4: {name: "H", val: "0"}
> 5: {name: "B", val: 0}
> 6: {name: "I", val: ""}
> 7: {name: "A", val: "0"}
> 8: {name: "E", val: 0}

下記のような条件をつけるとうまくソートできます。

昇順の場合

function comp(av, bv) {
  if (av === '' && bv === '') return 0;
  if (av === '') return -1;
  if (bv === '') return 1;
  return av < bv ? -1 : 1;
}

items.sort((a,b) => comp(a.val, b.val));

> 0: {name: "C", val: ""}
> 1: {name: "G", val: ""}
> 2: {name: "I", val: ""}
> 3: {name: "F", val: ""}
> 4: {name: "D", val: 0}
> 5: {name: "H", val: "0"}
> 6: {name: "B", val: 0}
> 7: {name: "A", val: "0"}
> 8: {name: "E", val: 0}

昇順、降順を指定させる場合はこのような関数にします。

function comp(asc, av, bv) {
  if (av === '' && bv === '') return 0;
  if (asc) {
    if (av === '') return -1;
    if (bv === '') return 1;
    return av < bv ? -1 : 1;
  } else {
    if (av === '') return 1;
    if (bv === '') return -1;
    return av < bv ? 1 : -1;
  }
}

// 昇順
items.sort((a,b) => comp(true, a.val, b.val));

> 0: {name: "C", val: ""}
> 1: {name: "G", val: ""}
> 2: {name: "I", val: ""}
> 3: {name: "F", val: ""}
> 4: {name: "D", val: 0}
> 5: {name: "H", val: "0"}
> 6: {name: "B", val: 0}
> 7: {name: "A", val: "0"}
> 8: {name: "E", val: 0}

// 降順
items.sort((a,b) => comp(false, a.val, b.val));

> 0: {name: "E", val: 0}
> 1: {name: "A", val: "0"}
> 2: {name: "B", val: 0}
> 3: {name: "H", val: "0"}
> 4: {name: "D", val: 0}
> 5: {name: "C", val: ""}
> 6: {name: "G", val: ""}
> 7: {name: "I", val: ""}
> 8: {name: "F", val: ""}
  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ