🎲

JavaScriptで日付が新しい順・古い順, あいうえお順のSort処理を実装してみた!

2024/01/28に公開

こんにちは、AIQ株式会社のフロントエンドエンジニアのまさぴょんです!
今回は、JavaScriptで日付が新しい順・古い順, あいうえお順のSort処理を実装する機会があったので、その知見と学びについて共有します。

前提: 基本のSort処理Logicを振り返る

本題の日付が新しい順(降順)・古い順(昇順), あいうえお順のSort処理の実装についての解説に入る前に、基本のSort処理Logicを振り返りましょう。

昇順と降順に関しては、以前にこちらの記事で説明しています。
https://masanyon.com/sql-web-dev-asc-desc/

JavaScriptで配列の要素を昇順や降順での並び替え・Sort処理するには、次のどちらかのメソッドを使用すればOKです。

  1. Array.prototype.sort()
    • 指定配列をSortします(破壊的変更)
  2. Array.prototype.toSorted()
    • 指定配列のコピーをSortして実行結果として、返却します。

sortメソッドで指定配列を昇順または降順でSortする(破壊的変更)

Array.prototype.sort()で指定配列を昇順または降順でSortすることができます。

const numberList = [1, 30, 4, 21, 100000];

/** 昇順・Sort */
const ascNumberList = numberList.sort((a, b) => a - b);
console.log("ascNumberList", ascNumberList); // ascNumberList (5) [1, 4, 21, 30, 100000]
console.log("numberList(元配列)", numberList); // numberList(元配列) (5) [1, 4, 21, 30, 100000]

/** 降順・Sort */
const descNumberList = numberList.sort((a, b) => b - a);
console.log("descNumberList", descNumberList); // descNumberList (5) [100000, 30, 21, 4, 1]
console.log("numberList(元配列)", numberList); // numberList(元配列) (5) [100000, 30, 21, 4, 1]

toSortedメソッドで指定配列のコピーを昇順または降順でSortする

Array.prototype.toSorted()で、指定配列のコピーをSortすることができます。

const numberList2 = [1, 30, 4, 21, 100000];

/** 昇順・Sort */
const ascNumberList2 = numberList2.toSorted((a, b) => a - b);

/** 降順・Sort */
const descNumberList2 = numberList2.toSorted((a, b) => b - a);

console.log("numberList2(元配列)", numberList2); // numberList2(元配列) (5) [1, 30, 4, 21, 100000]
console.log("ascNumberList2", ascNumberList2); // ascNumberList2 (5) [1, 4, 21, 30, 100000]
console.log("descNumberList2", descNumberList2); // descNumberList2 (5) [100000, 30, 21, 4, 1]

ここら辺の処理は、私の個人Tech Blogの記事内容から引用しています。
https://masanyon.com/javascript-array-list-sort-tosorted-asc-desc/

JavaScriptで日付が新しい順・古い順のSort処理を実装する

日付が新しい順・古い順のSort処理を実装する方法を考えていきますが、
その前に、日付の昇順(asc)と降順(desc)を比較すると次のようになります。

日付の古い順(昇順・asc) 日付の新しい順(降順・desc)
1995/12/12 2100/12/12
2050/12/12 2050/12/12
2100/12/12 1995/12/12

日付の古い順が昇順・asc であり、日付の新しい順が、降順・descである点に注意しましょう。
それでは、実装を見ていきます。

日付が新しい順(降順・desc)のSort処理を実装する

日付が新しい順(降順・desc)のSort処理は、次のようにして、実装することができます。

/**
 * NOTE: 日付の新しい順(降順) で Sortする
 * @param {string} a - 日付
 * @param {string} b - 日付
 * @return {number}
 */
function descTimeSort(a, b) {
  return a < b ? 1 : -1;
}

/** 文字列の日付リスト */
let dateList = [
  "2018/08/15",
  "2018/01/05",
  "2018/12/10",
  "2018/05/01",
  "2018/12/01",
  "2018/11/01",
  "2019/01/01",
  "2019/02/01",
];

// 日付の新しい順(降順・desc)
dateList.sort((a, b) => descTimeSort(a, b));
console.log("dateList Ver. 日付の新しい順(降順)", dateList);
// dateList Ver. 日付の新しい順(降順)  (8) ['2019/02/01', '2019/01/01', '2018/12/10', '2018/12/01', '2018/11/01', '2018/08/15', '2018/05/01', '2018/01/05']

/** Date Object の日付リスト */
const dateTimeList = [
  { id: 1, date: new Date(2020, 2, 22) },
  { id: 2, date: new Date(2020, 1, 1) },
  { id: 3, date: new Date(2019, 7, 28) },
  { id: 4, date: new Date(2080, 1, 1) },
  { id: 5, date: new Date(2100, 12, 12) },
];

// 日付の新しい順(降順・desc)
dateTimeList.sort((a, b) => descTimeSort(a.date, b.date));
console.log("dateTimeList Ver. 日付の新しい順(降順)", dateTimeList);
// [ 出力結果 ]
// dateTimeList Ver. 日付の新しい順(降順)
// 0: {id: 5, date: Wed Jan 12 2101 00:00:00 GMT+0900 (日本標準時)}
// 1: {id: 4, date: Thu Feb 01 2080 00:00:00 GMT+0900 (日本標準時)}
// 2: {id: 1, date: Sun Mar 22 2020 00:00:00 GMT+0900 (日本標準時)}
// 3: {id: 2, date: Sat Feb 01 2020 00:00:00 GMT+0900 (日本標準時)}
// 4: {id: 3, date: Wed Aug 28 2019 00:00:00 GMT+0900 (日本標準時)}

日付が古い順(昇順・asc)のSort処理を実装する

日付が古い順(昇順・asc)のSort処理は、次のようにして、実装することができます。

/**
 * NOTE: 日付の古い順(昇順) で Sortする
 * @param {string} a - 日付
 * @param {string} b - 日付
 * @return {number}
 */
function ascTimeSort(a, b) {
  return a > b ? 1 : -1;
}

// 日付の古い順(昇順)
dateList.sort((a, b) => ascTimeSort(a, b));
console.log("dateList Ver. 日付の古い順(昇順)", dateList);
// dateList Ver. 日付の古い順(昇順) (8) ['2018/01/05', '2018/05/01', '2018/08/15', '2018/11/01', '2018/12/01', '2018/12/10', '2019/01/01', '2019/02/01']

/** Date Object の日付リスト */
const dateTimeList2 = [
  { id: 1, date: new Date(2020, 2, 22) },
  { id: 2, date: new Date(2020, 1, 1) },
  { id: 3, date: new Date(2019, 7, 28) },
  { id: 4, date: new Date(2080, 1, 1) },
  { id: 5, date: new Date(2100, 12, 12) },
];
// 日付の古い順(昇順)
dateTimeList2.sort((a, b) => ascTimeSort(a.date, b.date));
console.log("dateTimeList2 Ver. 日付の古い順(昇順)", dateTimeList2);
// [ 出力結果 ]
// dateTimeList2 Ver. 日付の古い順(昇順)
// 0: {id: 3, date: Wed Aug 28 2019 00:00:00 GMT+0900 (日本標準時)}
// 1: {id: 2, date: Sat Feb 01 2020 00:00:00 GMT+0900 (日本標準時)}
// 2: {id: 1, date: Sun Mar 22 2020 00:00:00 GMT+0900 (日本標準時)}
// 3: {id: 4, date: Thu Feb 01 2080 00:00:00 GMT+0900 (日本標準時)}
// 4: {id: 5, date: Wed Jan 12 2101 00:00:00 GMT+0900 (日本標準時)}

最新登録日(新しい順)や古い順SortするLogicを構築

先述のLogicをベースに、今回実装することとなった、日付が新しい順・古い順で送付先(住所)の情報を並び替えるSampleCodeは次のようになります。

/** 1. 並び替えたい 対象の DataSet (送付先リスト) */
const addressList = [
  {
    user_id: "1000020339",
    city: "渋谷区",
    full_name: "ロボ ロボたま",
    address_line1: "",
    address_line2: null,
    building: "",
    district: "ハチ公前",
    first_name: "ロボたま",
    last_name: "ロボ",
    input_type: 2,
    post_code: "111-0078",
    phone_number: "1111111111",
    user_address_id: 1000020357,
    province: "東京都",
    create_time: "2024-01-24T08:00:33.472Z",
    update_time: null,
    default: false,
  },
  {
    user_id: "1000020339",
    city: "桐生市",
    full_name: "白桃 さん",
    address_line1: "メゾン白桃",
    address_line2: null,
    building: "",
    district: "広沢町",
    first_name: "さん",
    last_name: "白桃",
    input_type: 2,
    post_code: "111-0075",
    phone_number: "1111111111",
    user_address_id: 1000020358,
    province: "群馬県",
    create_time: "2024-01-24T08:07:23.560Z",
    update_time: null,
    default: true,
  },
  {
    user_id: "1000020339",
    city: "名古屋市",
    full_name: "もも たん",
    address_line1: "桃玉ハウス",
    address_line2: null,
    building: "",
    district: "中央区",
    first_name: "たん",
    last_name: "もも",
    input_type: 2,
    post_code: "111-0077",
    phone_number: "1111111111",
    user_address_id: 1000020359,
    province: "愛知県",
    create_time: "2024-01-26T08:07:23.560Z",
    update_time: null,
    default: true,
  },
  {
    user_id: "1000020339",
    city: "福岡市",
    full_name: "ぴゅぴゅ丸",
    address_line1: "ぴゅぴゅ丸ハウス",
    address_line2: null,
    building: "",
    district: "ぴゅぴゅ丸",
    first_name: "丸",
    last_name: "ぴゅぴゅ",
    input_type: 2,
    post_code: "111-0077",
    phone_number: "1111111111",
    user_address_id: 1000020360,
    province: "福岡県",
    create_time: "2024-01-26T08:12:23.560Z",
    update_time: null,
    default: true,
  },
  {
    user_id: "1000020339",
    city: "さいたま市",
    full_name: "ぷる たま",
    address_line1: "",
    address_line2: null,
    building: "",
    district: "東大宮",
    first_name: "たま",
    last_name: "ぷる",
    input_type: 2,
    post_code: "111-0088",
    phone_number: "1111111111",
    user_address_id: 1000020365,
    province: "埼玉県",
    create_time: "2024-01-25T09:30:47.730Z",
    update_time: null,
    default: false,
  },
];

/** 最新登録順(降順)で、Sortされた配列 */
const timeSortListAsc = [];

// 2. addressList の create_time を基準に「最新登録順(降順)」で Sort して timeSortList に pushする
addressList
  .sort((a, b) => {
    return a.create_time > b.create_time ? -1 : 1;
  })
  .forEach((address) => {
    timeSortListAsc.push(address);
  });
console.log("最新登録順(降順)", timeSortListAsc);

console.log("--------------------------");

/** 古い順(昇順) で、Sortされた配列 */
const timeSortListDesc = [];

// 3. 古い順(昇順): addressList の create_time を基準に「古い順(昇順)」で Sort して timeSortList に pushする
addressList
  .sort((a, b) => {
    return a.create_time < b.create_time ? -1 : 1;
  })
  .forEach((address) => {
    timeSortListDesc.push(address);
  });
console.log("古い順(昇順)", timeSortListDesc);

JavaScriptであいうえお順のSort処理を実装する

あいうえお順のSort処理を実装する方法を考えていきます。
次のように、日本語に対して、Array.prototype.sort()を使用すると、漢字など一部でSort処理があいうえお順にならない事象が発生します。

const array = ["う", "い", "あ", "ウ", "イ", "ア", "宇", "井", "亜", "a", "i", "u"];

array.sort();
console.log(array);
// 出力結果 => [a,i,u,あ,い,う,ア,イ,ウ,井,亜,宇]

このような事象が起こるため、日本語の50音順にソートしたい場合はlocaleCompareIntl.Collatorを利用します。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

const array = ["う", "い", "あ", "ウ", "イ", "ア", "宇", "井", "亜", "a", "i", "u"];

array.sort((a, b) => {
  return a.localeCompare(b, 'ja');
});
console.log(array);
// 出力結果 => [a,i,u,あ,ア,い,イ,う,ウ,亜,井,宇]

今回、実装した、より具体的なSampleCodeでは、読み方が複数ある漢字であることも考慮して、
漢字の読み仮名(ひらがな)をDataSetに追加する対応を実施しています。
読み仮名(ひらがな)を用意しておけば、正しいあいうえお順のSort処理を実行することができます。

/** 1. 都道府県 DataSet を用意する (name: 漢字, ruby: ひらがな)  */
const proviceItems = [
  { name: "北海道", ruby: "ほっかいどう" },
  { name: "青森県", ruby: "あおもりけん" },
  { name: "岩手県", ruby: "いわてけん" },
  { name: "宮城県", ruby: "みやぎけん" },
  { name: "秋田県", ruby: "あきたけん" },
  { name: "山形県", ruby: "やまがたけん" },
  { name: "福島県", ruby: "ふくしまけん" },
  { name: "茨城県", ruby: "いばらきけん" },
  { name: "栃木県", ruby: "とちぎけん" },
  { name: "群馬県", ruby: "ぐんまけん" },
  { name: "埼玉県", ruby: "さいたまけん" },
  { name: "千葉県", ruby: "ちばけん" },
  { name: "東京都", ruby: "とうきょうと" },
  { name: "神奈川県", ruby: "かながわけん" },
  { name: "新潟県", ruby: "にいがたけん" },
  { name: "富山県", ruby: "とやまけん" },
  { name: "石川県", ruby: "いしかわけん" },
  { name: "福井県", ruby: "ふくいけん" },
  { name: "山梨県", ruby: "やまなしけん" },
  { name: "長野県", ruby: "ながのけん" },
  { name: "岐阜県", ruby: "ぎふけん" },
  { name: "静岡県", ruby: "しずおかけん" },
  { name: "愛知県", ruby: "あいちけん" },
  { name: "三重県", ruby: "みえけん" },
  { name: "滋賀県", ruby: "しがけん" },
  { name: "京都府", ruby: "きょうとふ" },
  { name: "大阪府", ruby: "おおさかふ" },
  { name: "兵庫県", ruby: "ひょうごけん" },
  { name: "奈良県", ruby: "ならけん" },
  { name: "和歌山県", ruby: "わかやまけん" },
  { name: "鳥取県", ruby: "とっとりけん" },
  { name: "島根県", ruby: "しまねけん" },
  { name: "岡山県", ruby: "おかやまけん" },
  { name: "広島県", ruby: "ひろしまけん" },
  { name: "山口県", ruby: "やまぐちけん" },
  { name: "徳島県", ruby: "とくしまけん" },
  { name: "香川県", ruby: "かがわけん" },
  { name: "愛媛県", ruby: "えひめけん" },
  { name: "高知県", ruby: "こうちけん" },
  { name: "福岡県", ruby: "ふくおかけん" },
  { name: "佐賀県", ruby: "さがけん" },
  { name: "長崎県", ruby: "ながさきけん" },
  { name: "熊本県", ruby: "くまもとけん" },
  { name: "大分県", ruby: "おおいたけん" },
  { name: "宮崎県", ruby: "みやざきけん" },
  { name: "鹿児島県", ruby: "かごしまけん" },
  { name: "沖縄県", ruby: "おきなわけん" },
];

// 2. 事前に、都道府県の読み仮名(ruby: ひらがな) を基準に あいうえお順 で Sort する
proviceItems.sort((a, b) => a.ruby.localeCompare(b.ruby), "ja");
console.log("proviceItems", proviceItems);

/** 3. 並び替えたい 対象の DataSet (送付先リスト) */
const addressList = [
  {
    user_id: "1000020339",
    city: "渋谷区",
    full_name: "ロボ ロボたま",
    address_line1: "",
    address_line2: null,
    building: "",
    district: "ハチ公前",
    first_name: "ロボたま",
    last_name: "ロボ",
    input_type: 2,
    post_code: "111-0078",
    phone_number: "1111111111",
    user_address_id: 1000020357,
    province: "東京都",
    create_time: "2024-01-24T08:00:33.472Z",
    update_time: null,
    default: false,
  },
  {
    user_id: "1000020339",
    city: "桐生市",
    full_name: "白桃 さん",
    address_line1: "メゾン白桃",
    address_line2: null,
    building: "",
    district: "広沢町",
    first_name: "さん",
    last_name: "白桃",
    input_type: 2,
    post_code: "111-0075",
    phone_number: "1111111111",
    user_address_id: 1000020358,
    province: "群馬県",
    create_time: "2024-01-24T08:07:23.560Z",
    update_time: null,
    default: true,
  },
  {
    user_id: "1000020339",
    city: "名古屋市",
    full_name: "もも たん",
    address_line1: "桃玉ハウス",
    address_line2: null,
    building: "",
    district: "中央区",
    first_name: "たん",
    last_name: "もも",
    input_type: 2,
    post_code: "111-0077",
    phone_number: "1111111111",
    user_address_id: 1000020359,
    province: "愛知県",
    create_time: "2024-01-26T08:07:23.560Z",
    update_time: null,
    default: true,
  },
  {
    user_id: "1000020339",
    city: "福岡市",
    full_name: "ぴゅぴゅ丸",
    address_line1: "ぴゅぴゅ丸ハウス",
    address_line2: null,
    building: "",
    district: "ぴゅぴゅ丸",
    first_name: "丸",
    last_name: "ぴゅぴゅ",
    input_type: 2,
    post_code: "111-0077",
    phone_number: "1111111111",
    user_address_id: 1000020360,
    province: "福岡県",
    create_time: "2024-01-26T08:12:23.560Z",
    update_time: null,
    default: true,
  },
  {
    user_id: "1000020339",
    city: "さいたま市",
    full_name: "ぷる たま",
    address_line1: "",
    address_line2: null,
    building: "",
    district: "東大宮",
    first_name: "たま",
    last_name: "ぷる",
    input_type: 2,
    post_code: "111-0088",
    phone_number: "1111111111",
    user_address_id: 1000020365,
    province: "埼玉県",
    create_time: "2024-01-25T09:30:47.730Z",
    update_time: null,
    default: false,
  },
];

// 都道府県 を基準に あいうえお順 で Sort する
addressList.sort((addressA, addressB) => {
  /** 都道府県名 A */
  const provinceA = addressA.province;
  console.log("都道府県 Part A", provinceA);
  /** 都道府県名 B */
  const provinceB = addressB.province;
  console.log("都道府県 Part B", provinceB);

  /** 都道府県名 A の index(あいうえお順で並んでいる番号) */
  const orderindexA = proviceItems.findIndex(
    (provice) => provice.name === provinceA
  );
  /** 都道府県名 B の index(あいうえお順で並んでいる番号) */
  const orderindexB = proviceItems.findIndex(
    (provice) => provice.name === provinceB
  );
  console.log("あいうえお順で並んだ際の順序(番号) Part A", orderindexA);
  console.log("あいうえお順で並んだ際の順序(番号) Part B", orderindexB);

  // 昇順ソート(あいうえお順)
  return orderindexA - orderindexB;
});

console.log("addressList", addressList);

Code中のコメントに処理のポイントは記述していますが、まとめると次のとおりです。

まとめ

機能開発にて、日付が新しい順・古い順, あいうえお順のSort処理の方法について学べてよかったです。
ぜひご活用してみてください。

個人で、Blogもやっています、よかったら見てみてください。

https://masanyon.com/

注意事項

この記事は、AIQ 株式会社の社員による個人の見解であり、所属する組織の公式見解ではありません。

求む、冒険者!

AIQ株式会社では、一緒に働いてくれるエンジニアを絶賛、募集しております🐱🐹✨

詳しくは、Wantedly (https://www.wantedly.com/companies/aiqlab)を見てみてください。

参考・引用

https://zenn.dev/manase/scraps/2e35c6f51ba726

https://masanyon.com/javascript-array-list-sort-tosorted-asc-desc/

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/toSorted

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

AIQ Tech Blog (有志)

Discussion