Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Leetcode 2705. Compact Object

2025年09月27日に「Dev.to」が公開したITニュース「Leetcode 2705. Compact Object」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

JavaScriptの`compactObject`関数は、オブジェクトや配列内の`false`や`null`、`0`、空文字列などの「偽の値」を再帰的に取り除き、真の値のみを含む新しい構造を生成する。これはデータの整理や軽量化に役立つ。

出典: Leetcode 2705. Compact Object | Dev.to公開日:

ITニュース解説

「Compact Object」問題は、与えられたオブジェクトや配列の中から、特定の「意味のない」と見なされる値、つまり「falsy(フォルシー)」な値を取り除き、「truthy(トゥルーシー)」な値だけを残して、よりコンパクトな新しいデータ構造を作り出す処理について考える問題だ。現代のITシステムでは、データは非常に複雑になりがちで、ユーザーが入力しなかった項目やシステムが生成しなかったデフォルト値など、無駄な情報がオブジェクトや配列の中に含まれている場合がある。このような不要なデータが残っていると、処理の効率が低下したり、予期せぬエラーの原因になったりすることがあるため、データ整理は非常に重要だ。この問題を解決するのが「Compact Object」の役割だ。

このJavaScriptコードは、compactObjectという名前の関数を定義している。この関数は、処理の対象となるobj(オブジェクトまたは配列)を引数として受け取り、整理された新しいオブジェクトまたは配列を返すことを目指している。

コードの冒頭には、まず重要な条件分岐がある。 if (typeof obj !== 'object' || obj == null) この行は、処理の対象であるobjが、オブジェクトでも配列でもない場合(例えば、単なる文字列、数値、真偽値など)や、nullである場合に適用される。JavaScriptでは、配列もtypeof演算子を使うと'object'と評価されるため、この条件でオブジェクト全般をカバーしている。もしobjがこれらの条件に合致する、つまり、それ以上内部に構造を持たない単純な値であれば、何も「コンパクト化」する対象がないため、そのobjをそのまま返すという基本ルールを定めている。これは、後述する「再帰関数」と呼ばれる処理において非常に重要な「ベースケース」(処理を終了する条件)にあたる。

次に、処理対象がオブジェクトまたは配列であることが確定した後の流れを見ていこう。 const isArray = Array.isArray(obj) const result = Array.isArray(obj) ? [] : {} ここでは、objが配列なのか、それとも通常のオブジェクトなのかをArray.isArray()という関数を使って判別している。この判別結果はisArrayという変数に保持され、後の処理で利用される。そして、最終的な結果を格納するための空のコンテナとして、resultという変数を準備している。もしobjが配列であれば空の配列[]を、オブジェクトであれば空のオブジェクト{}を初期値として設定する。これは、元のobjの型に応じて、結果も同じ型の構造で返すための準備だ。

さらに、objの内部にある要素を一つずつ見ていくための準備が続く。 const keys = Object.keys(obj) for (const key of keys) { ... } Object.keys(obj)は、与えられたオブジェクト(または配列)が持つすべての「キー」(オブジェクトのプロパティ名、配列のインデックス)を文字列の配列として取り出す関数だ。このkeysを使ってfor...ofループを回すことで、objが持つすべての要素に対して順番に処理を行うことができるようになる。

ループの内部では、いよいよ本質的な処理が始まる。 let value = obj[key] let compactedValue = compactObject(value) まず、現在のkeyに対応するvalueを取り出す。そして、このvalueに対して、なんと自分自身の関数であるcompactObjectを再度呼び出している。これが「再帰」と呼ばれる処理の核心だ。もしvalueがさらに内部にオブジェクトや配列を含んでいる場合、その内部の構造に対しても同じ「コンパクト化」のルールが適用される。例えば、objの中に{ a: 1, b: { c: 0, d: 2 } }のような構造があった場合、bというキーに対応する{ c: 0, d: 2 }というオブジェクトに対しても、このcompactObject関数が再び適用される。このようにして、オブジェクトや配列の階層構造を深くまで辿りながら、すべての要素をチェックしていくのだ。

再帰呼び出しの結果、compactedValueには、子要素がコンパクト化された結果が格納される。次に、このcompactedValueを最終結果に含めるかどうかを判断する重要な部分だ。 if (Boolean(compactedValue)) { ... } ここで登場するBoolean()関数は、JavaScriptにおける「truthy」と「falsy」という概念を理解する上で非常に重要だ。JavaScriptでは、真偽値であるtruefalseだけでなく、他の多くの値も条件式の中で真偽値として評価される。

  • falsyな値: false0(数値のゼロ)、-0(負のゼロ)、0n(BigIntのゼロ)、""(空文字列)、nullundefinedNaN(Not-a-Number)
  • truthyな値: 上記以外のすべての値(例えば、1"hello"[]{}function(){} など) Boolean(compactedValue)は、compactedValueがfalsyな値であればfalseを、truthyな値であればtrueを返す。つまり、このif文は、「compactedValueがfalsyではない、つまり意味のある値である場合に限り」という条件を意味している。falsyな値は、コンパクト化された結果からは取り除かれることになる。

もしcompactedValueがtruthyであると判断された場合、それが最終結果resultに追加される。 if (isArray) { result.push(compactedValue) } else { result[key] = compactedValue } ここで、最初にisArrayで判別した結果が再び使われる。もし元のobjが配列であったならば、resultも配列として初期化されているので、push()メソッドを使ってcompactedValueを配列の末尾に追加する。一方、元のobjがオブジェクトであったならば、resultもオブジェクトなので、元のkeyを使ってcompactedValueをプロパティとして設定する。これにより、元の構造を保ちつつ、不要なfalsyな値が取り除かれた新しいオブジェクトや配列が構築されていく。

ループがobjのすべてのキーに対して完了すると、最後に整理されたresultが関数から返される。 return result

このcompactObject関数は、再帰的な処理とJavaScriptのfalsy/truthyの概念を巧みに利用することで、複雑なデータ構造から不要な要素を効率的に取り除くことを可能にする。システム開発において、APIからのレスポンスデータを整形したり、ユーザーからの入力をクリーンアップしたりする場面で、このようなデータ整理のロジックは非常に役立つ。再帰処理は、はじめは理解が難しいと感じるかもしれないが、このように階層的なデータを扱う際には非常に強力なツールとなる。このコードは、再帰の基本的なパターンと、JavaScriptの言語特性を理解する上で良い教材となるだろう。

関連コンテンツ