テーマの整理:「並び順保存」とは何か
「並び順保存」は、ユーザーが並べ替えた配列の順番を、あとで再現できるように“記録しておく”ユーティリティのことです。 業務だと、次のような場面でよく出てきます。
- 画面でドラッグ&ドロップして並び替えた順番を、次回表示時にも維持したい
- ユーザーごとに「お気に入りの並び順」を保存しておきたい
- API から取ってきたデータを「保存済みの並び順」に従って並べたい
ポイントは、「並び替えた配列そのもの」を保存するのではなく、 “並び順を表す情報”を保存しておいて、あとから配列に適用することです。
基本コンセプト:「ID の順番を保存して、あとから並べ替えに使う」
並び順を「配列そのもの」で保存する問題点
例えば、ユーザー一覧を並び替えて、そのまま配列を保存したとします。
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
];
const reordered = [
{ id: 2, name: "Bob" },
{ id: 1, name: "Alice" },
];
// この reordered を丸ごと保存する
JavaScript一見これで良さそうですが、 あとで API から最新のユーザー一覧を取ってきたときに、
- 新しいユーザーが増えている
- 既存ユーザーの情報が変わっている
などが起きると、「古い配列をそのまま使う」わけにはいきません。
そこで、「並び順だけ」を保存しておく、という発想が出てきます。
並び順を「ID の配列」として保存する
並び順をこう表現します。
const order = [2, 1]; // id の順番だけを保存
JavaScriptこの order を保存しておいて、 あとから最新の users 配列に対して「この順番で並べ替える」ようにします。
これが「並び順保存」の基本コンセプトです。
ユーティリティ 1:並び順(ID 配列)を保存する
シナリオ
ユーザーが UI 上で並び替えた結果として、 並び替え後の配列 reorderedUsers が手元にある。
そこから「並び順だけ」を取り出して保存したい。
実装:extractOrder
function extractOrder(records, idField = "id") {
if (!Array.isArray(records) || records.length === 0) {
return [];
}
return records.map((r) => r[idField]);
}
JavaScript重要ポイントの深掘り
「並び順=ID の並び」として定義する 並び順を「レコードそのもの」ではなく「ID の並び」として扱うことで、 あとから最新データに対しても再利用できるようになります。
保存するのはシンプルな配列だけ [2, 1, 5, 3, ...] のような数値・文字列の配列は、 ローカルストレージ・DB・API などに保存しやすく、 シリアライズ(JSON 化)も簡単です。
例題 1:並び替え後の配列から並び順を取り出して保存する
const reorderedUsers = [
{ id: 2, name: "Bob" },
{ id: 1, name: "Alice" },
];
const order = extractOrder(reorderedUsers);
console.log(order); // [2, 1]
// この order を localStorage や DB に保存しておく
JavaScriptこれで、「ユーザーが決めた並び順」を、 軽量な形で保存できました。
ユーティリティ 2:保存した並び順を配列に適用する
シナリオ
次回画面表示時に、API から最新のユーザー一覧を取得した。 同時に、以前保存しておいた order = [2, 1] も読み込んだ。
この 2 つを組み合わせて、「保存済みの並び順」で並べたい。
実装:applyOrder
function applyOrder(records, order, idField = "id") {
if (!Array.isArray(records) || records.length === 0) {
return [];
}
if (!Array.isArray(order) || order.length === 0) {
return records.slice(); // 並び順がなければそのまま返す
}
const map = new Map();
records.forEach((r) => {
map.set(r[idField], r);
});
const ordered = [];
order.forEach((id) => {
const item = map.get(id);
if (item) {
ordered.push(item);
}
});
const usedIds = new Set(order);
records.forEach((r) => {
if (!usedIds.has(r[idField])) {
ordered.push(r);
}
});
return ordered;
}
JavaScript重要ポイントの深掘り
ID → レコードのマップを作る Map を使って、id からレコードを素早く引けるようにしています。 これで、order の順番に従ってレコードを並べることができます。
order にないレコードも「最後に追加」する 新しく追加されたユーザーなど、 保存済みの order に含まれていないレコードは、 最後にまとめて追加しています。
これにより、
- 既存ユーザーは「保存済みの並び順」で並ぶ
- 新規ユーザーは「並び順の末尾」に追加される
という自然な挙動になります。
例題 2:保存済みの並び順を最新ユーザー一覧に適用する
const latestUsers = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Carol" },
];
const savedOrder = [2, 1];
const orderedUsers = applyOrder(latestUsers, savedOrder);
console.log(orderedUsers);
JavaScript出力イメージはこうなります。
[
{ id: 2, name: "Bob" }, // savedOrder の 2
{ id: 1, name: "Alice" }, // savedOrder の 1
{ id: 3, name: "Carol" }, // savedOrder にないので最後に追加
]
JavaScriptここでのポイントは、
- 「保存済みの並び順」が優先される
- 新しいデータもちゃんと表示される
というバランスが取れていることです。
ユーティリティ 3:並び順を「ユーザーごと・画面ごと」に保存する
シナリオ
ユーザー A とユーザー B で、 同じ一覧画面でも「好みの並び順」が違う。
また、画面ごとに並び順を変えたい(ユーザー一覧・商品一覧など)。
保存キーの設計
ローカルストレージなどに保存するときは、 「誰の」「どの画面の」並び順かを区別するキーを決めます。
function makeOrderKey(userId, screenId) {
return `order:${userId}:${screenId}`;
}
JavaScript実装:saveOrder / loadOrder(ローカルストレージ版)
function saveOrder(key, order) {
try {
const json = JSON.stringify(order);
localStorage.setItem(key, json);
} catch (e) {
console.error("並び順の保存に失敗しました", e);
}
}
function loadOrder(key) {
try {
const json = localStorage.getItem(key);
if (!json) return [];
const order = JSON.parse(json);
return Array.isArray(order) ? order : [];
} catch (e) {
console.error("並び順の読み込みに失敗しました", e);
return [];
}
}
JavaScript重要ポイントの深掘り
キー設計で「誰の・どの画面の」を区別する order:ユーザーID:画面ID のようなキーにしておくと、 ユーザーごと・画面ごとに並び順を分けて保存できます。
保存・読み込みは“失敗しても壊れない”ようにする 例外が出てもアプリが落ちないように、 try/catch でエラーを握りつぶしつつログだけ出しています。 読み込みに失敗したときは「空の並び順」として扱うことで、 画面は普通に表示されます。
例題 3:ユーザーごと・画面ごとに並び順を保存して適用する
const userId = "user-123";
const screenId = "user-list";
const key = makeOrderKey(userId, screenId);
const reorderedUsers = [
{ id: 2, name: "Bob" },
{ id: 1, name: "Alice" },
];
const orderToSave = extractOrder(reorderedUsers);
saveOrder(key, orderToSave);
// 次回表示時
const latestUsers = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Carol" },
];
const savedOrder = loadOrder(key);
const orderedUsers = applyOrder(latestUsers, savedOrder);
console.log(orderedUsers);
JavaScriptこれで、
- ユーザー 123 がユーザー一覧画面で決めた並び順
- それを次回表示時に再現
という流れが実現できます。
並び順保存ユーティリティで意識してほしい重要ポイント
「並び順=ID の並び」として扱う
並び順保存の一番大事なポイントは、 「並び順そのものではなく、ID の並びを保存する」という発想です。
これによって、
- 最新データに対しても並び順を再利用できる
- 保存するデータが軽く・シンプルになる
- API や DB の変更にも強くなる
というメリットが得られます。
「保存済みの並び順」と「最新データ」をどう統合するかを決める
applyOrder の設計が、並び順保存の“性格”を決めます。
- order にある ID は、その順番を優先する
- order にない ID は、最後に追加する
- order にあるけど、最新データにない ID は無視する
このルールを明確にしておくと、 ユーザーにとって「自然な挙動」になります。
手を動かして「並び順保存」の感覚をつかむ
次のコードを実行して、
- 並び替え後の配列から並び順を抽出
- 並び順を保存(ここではメモリ上)
- 最新データに並び順を適用
という一連の流れを体感してみてください。
function extractOrder(records, idField = "id") {
if (!Array.isArray(records) || records.length === 0) {
return [];
}
return records.map((r) => r[idField]);
}
function applyOrder(records, order, idField = "id") {
if (!Array.isArray(records) || records.length === 0) {
return [];
}
if (!Array.isArray(order) || order.length === 0) {
return records.slice();
}
const map = new Map();
records.forEach((r) => {
map.set(r[idField], r);
});
const ordered = [];
order.forEach((id) => {
const item = map.get(id);
if (item) ordered.push(item);
});
const usedIds = new Set(order);
records.forEach((r) => {
if (!usedIds.has(r[idField])) {
ordered.push(r);
}
});
return ordered;
}
function demo() {
const reorderedUsers = [
{ id: 2, name: "Bob" },
{ id: 1, name: "Alice" },
];
const order = extractOrder(reorderedUsers);
console.log("saved order:", order);
const latestUsers = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Carol" },
];
const orderedUsers = applyOrder(latestUsers, order);
console.log("ordered users:", orderedUsers);
}
demo();
JavaScriptまとめ:並び順保存ユーティリティで「ユーザーの“並べ方の好み”を、ちゃんと覚えておく」
並び順保存は、 「ユーザーが決めた並び方の好みを、ID の並びとして記録し、最新データに適用するためのユーティリティ」です。
プロジェクトでは、例えばこうまとめておくと扱いやすいです。
export function extractOrder(records, idField = "id") { ... }
export function applyOrder(records, order, idField = "id") { ... }
export function makeOrderKey(userId, screenId) { ... }
export function saveOrder(key, order) { ... }
export function loadOrder(key) { ... }
JavaScriptそして、
- 並び替え操作の直後
- 画面表示の直前
など、「並び順が変わる・並び順を使う」場面で必ずこのユーティリティを通す。
そうすると、 ユーザーの「この並びが好き」という感覚を、 アプリがちゃんと覚えていてくれるようになります。
配列の中身だけじゃなく、「並び方」まで味方につける—— それが、並び順保存ユーティリティの役割です。
