何をしたいユーティリティか:「空要素削除」
ここでの「空要素削除」は、配列の中から「いらない空っぽの値」を取り除いて、きれいな配列にする処理です。
英語だと compact や clean などと呼ばれます。
業務では、例えばこんな場面でよく出てきます。
フォーム入力で「空の行」が混ざっているので、送信前に消したい。
CSV をパースしたら、null や undefined、空文字がたくさん入っていた。
API からのレスポンスに「値なし」の要素が混ざっていて、集計の邪魔になる。
こういうときに「空要素削除ユーティリティ」があると、毎回同じ条件でクリーンアップできて、バグも減ります。
まず決めるべきこと:「何を“空”とみなすか」
よくある「空」の候補
「空要素削除」で一番大事なのは、何を“空”とみなすかを決めることです。
よく候補に上がるのは次のような値です。
nullundefined
空文字 ""
空白だけの文字 " "NaN0(これは多くの場合「空」ではなく「有効な値」です)
ここを曖昧にしたまま書き始めると、「このケースでは消えるのに、あっちでは消えない」といった混乱が起きます。
なので、まずは「最小限の空」として null と undefined だけを消すところから始めるのがおすすめです。
基本形:null / undefined を消す空要素削除
一番シンプルな compact ユーティリティ
まずは、「null と undefined を削除する」だけのシンプルなユーティリティを書きます。
function compactNullable(array) {
if (!Array.isArray(array)) {
return [];
}
return array.filter((item) => item != null);
}
JavaScriptここでのポイントは、item != null という条件です。!=(ゆるい等価)は、null と undefined の両方にマッチします。
item != null はitem !== null && item !== undefined
と同じ意味です。
つまり、「null と undefined だけを消して、それ以外は全部残す」動きになります。
実際の動き
const data = [1, null, 2, undefined, 3, 0, "", false];
const cleaned = compactNullable(data);
// [1, 2, 3, 0, "", false]
JavaScript0 や空文字 ""、false は「有効な値」として残っています。
「とりあえず null/undefined だけ消したい」という場面では、この compactNullable で十分です。
もう一歩踏み込む:「空文字」や「空白だけ」も消したい
文字列入力を扱うときの「空」の扱い
フォームや CSV など、文字列入力を扱う場面では、""(完全な空文字)や " "(空白だけの文字列)も「空」とみなしたいことが多いです。
その場合は、「空文字・空白だけの文字列も削除する」ユーティリティを用意します。
function isEmptyValue(value) {
if (value == null) {
return true;
}
if (typeof value === "string") {
return value.trim().length === 0;
}
return false;
}
function compactEmpty(array) {
if (!Array.isArray(array)) {
return [];
}
return array.filter((item) => !isEmptyValue(item));
}
JavaScriptisEmptyValue が「空かどうか」を判定する関数です。compactEmpty は、「空ではないものだけを残す」フィルタです。
ここでの重要ポイントは、trim() を使っていることです。" " のような空白だけの文字列も、trim() すると "" になり、長さ 0 と判定できます。
実際の動き
const data = [1, null, 2, undefined, 3, 0, "", " ", "A", false];
const cleaned = compactEmpty(data);
// [1, 2, 3, 0, "A", false]
JavaScriptnull / undefined / "" / " " は削除され、0 や "A"、false は残っています。
条件をカスタマイズできる「汎用フィルタ」型ユーティリティ
「プロジェクトごとに“空”の定義が違う」問題
現実のプロジェクトでは、「この画面では 0 も空扱い」「この処理では 0 は有効」といった違いが出てきます。
そのたびに compactEmpty をコピーして条件を変えるのはつらいので、
「判定関数を渡せる汎用ユーティリティ」を用意しておくと便利です。
function compactBy(array, isEmpty) {
if (!Array.isArray(array)) {
return [];
}
if (typeof isEmpty !== "function") {
return array.slice();
}
return array.filter((item) => !isEmpty(item));
}
JavaScriptisEmpty は、「その値が“空”かどうかを判定する関数」です。true を返したものは削除され、false を返したものは残ります。
実際の使い方
例えば、「0 も空扱いにしたい」場合はこう書けます。
const data = [0, 1, 2, null, "", "A"];
const cleaned = compactBy(data, (value) => {
if (value == null) return true;
if (typeof value === "string" && value.trim().length === 0) return true;
if (value === 0) return true;
return false;
});
// [1, 2, "A"]
JavaScript「空の定義」を関数として外に出しておくことで、
処理ごとに柔軟に変えられるようになります。
空要素削除を業務でどう使うか
例1:フォームの「空行」を送信前に削除する
ユーザーが「明細行を追加」できるフォームで、
空の行(何も入力されていない行)が混ざることはよくあります。
const rows = [
{ name: "A", qty: 1 },
{ name: "", qty: null },
{ name: "B", qty: 2 },
];
JavaScript「名前も数量も空なら、その行は送信しない」というルールにしたい場合、
まず「行が空かどうか」を判定する関数を書きます。
function isEmptyRow(row) {
if (!row || typeof row !== "object") return true;
const nameEmpty = !row.name || String(row.name).trim().length === 0;
const qtyEmpty = row.qty == null || row.qty === "";
return nameEmpty && qtyEmpty;
}
const cleanedRows = rows.filter((row) => !isEmptyRow(row));
JavaScriptこれは「配列の空要素削除」というより「オブジェクトの空判定」ですが、
考え方は同じで、「空の定義を関数に閉じ込めて、filter で削除する」スタイルです。
例2:CSV パース後の「空行」を削除する
CSV をパースすると、末尾に空行が入っていたり、
途中に「全部空の列」の行が紛れ込んでいたりします。
const rows = [
["A", "1"],
["", ""],
["B", "2"],
[""],
];
JavaScript「全てのセルが空なら、その行を削除する」ユーティリティはこう書けます。
function isEmptyCsvRow(row) {
if (!Array.isArray(row) || row.length === 0) return true;
return row.every((cell) => {
if (cell == null) return true;
if (typeof cell === "string" && cell.trim().length === 0) return true;
return false;
});
}
const cleanedRows = rows.filter((row) => !isEmptyCsvRow(row));
JavaScriptここでも、「空の定義」を関数に閉じ込めて、filter で削除しています。
「空要素削除」ユーティリティ設計で意識してほしいポイント
1. 「空の定義」をはっきりさせる
一番大事なのは、「何を空とみなすか」を明文化することです。
null / undefined だけなのか。
空文字 "" も含めるのか。
空白だけの文字 " " も含めるのか。0 や false はどう扱うのか。
これをユーティリティのレベルで決めておくと、
「この処理では消えるのに、あっちでは消えない」といった不思議な挙動を防げます。
2. 「破壊的」にしない(新しい配列を返す)
空要素削除は、基本的に「新しい配列を返す非破壊的な関数」にしておくのがおすすめです。
filter は元の配列を変更しないので、安全です。
元の配列を直接 splice でいじると、「どこで消えたのか」が追いにくくなります。
業務コードでは、「元データはそのまま」「クリーンな配列を別で持つ」というスタイルのほうが、
デバッグしやすく、バグも減ります。
3. 「null だけ」「文字列も含めて」「カスタム」の3段階を用意する
実装としては、次の 3 段階を用意しておくと使いやすいです。
compactNullable … null / undefined だけを削除する。compactEmpty … null / undefined / 空文字 / 空白だけの文字列を削除する。compactBy … 呼び出し側が「空の定義」を関数で渡せる汎用版。
これを揃えておくと、「とりあえず null だけ消したい」「文字列もきれいにしたい」「この画面だけ特別なルールにしたい」といったニーズに、きれいに対応できます。
少し手を動かして感覚をつかむ
コンソールで、次のようなコードを実際に打ってみてください。
const data = [1, null, 2, undefined, 3, 0, "", " ", "A", false];
compactNullable(data);
compactEmpty(data);
compactBy(data, (value) => {
if (value == null) return true;
if (typeof value === "string" && value.trim().length === 0) return true;
if (value === 0) return true;
return false;
});
JavaScript「どの値が残って、どの値が消えるか」「空の定義を変えると結果がどう変わるか」を、自分の目で確認してみてください。
そのうえで、自分のプロジェクトに
export function compactNullable(...) { ... }
export function compactEmpty(...) { ... }
export function compactBy(...) { ... }
JavaScriptのような関数を置き、「配列をきれいにしたくなったら、必ずこの“空要素削除ユーティリティ”を通す」というルールを作ってみてください。
そうすると、「場当たり的な filter 条件の乱立」から、「意図と一貫性を持ったクレンジング処理」に一段ステップアップしていきます。
