1000の判定条件には1000のifを書く必要がある? if 分岐ステートメントを最適化するにはどうすればよいですか?次の記事ではブランチの最適化を実現する方法について説明しますので、皆様のお役に立てれば幸いです。
最近、インターネットサーフィン中に次のコードを見つけました:
function getUserDescribe(name) { if (name === "小刘") { console.log("刘哥哥"); } else if (name === "小红") { console.log("小红妹妹"); } else if (name === "陈龙") { console.log("大师"); } else if (name === "李龙") { console.log("师傅"); } else if (name === "大鹏") { console.log("恶人"); } else { console.log("此人比较神秘!"); } }
一見したところ、何も異常を感じませんでしたが、もし何か異常がある場合は、判定条件が1000個、この書き方だとif
分岐を1000個書くのは難しいでしょうか?
多数の if
ブランチを記述し、ブランチ 内に ブランチも存在する可能性がある場合、コード全体の可読性と保守性が低下すると想像できます。実際の開発ではこれが頭の痛い問題ですが、これらの問題を回避しながら要件を達成する方法はあるのでしょうか? [推奨学習: JavaScript ビデオ チュートリアル ]
これには ブランチの最適化 が含まれます。変更しましょう私たちの考え方と上記のコード構造を最適化します。
function getUserDescribe(name) { const describeForNameMap = { 小刘: () => console.log("刘哥哥"), 小红: () => console.log("小红妹妹"), 陈龙: () => console.log("大师"), 李龙: () => console.log("师傅"), 大鹏: () => console.log("恶人"), }; describeForNameMap[name] ? describeForNameMap[name]() : console.log("此人比较神秘!"); }
問題コード内の判定はすべて単純な 均等判定 であるため、これらの判定条件をオブジェクト の属性として記述することができます。 descriptionForNameMap
、これらの属性に対応する値が条件成立後の処理関数となります。
その後は、getUserDescribe
関数で受け取ったパラメーターを通じて、describeForNameMap
オブジェクト内の対応する値を取得するだけです。値が存在する場合は、その値を実行します。 (値は関数であるため)。
このように、元の if
分岐判定は、単純な key value
対応値に変換され、条件と処理関数が 1 対 1 に対応して明確になります。一目でわかる。
次に、if
分岐の判定条件が単純な等価判定だけではなく、いくつかの計算を含んでいるとします。計算する必要がある式が次の場合はどうすればよいですか? (以下に示すように)
function getUserDescribe(name) { if (name.length > 3) { console.log("名字太长"); } else if (name.length < 2) { console.log("名字太短"); } else if (name[0] === "陈") { console.log("小陈"); } else if (name[0] === "李" && name !== "李鹏") { console.log("小李"); } else if (name === "李鹏") { console.log("管理员"); } else { console.log("此人比较神秘!"); } }
この構造のコードでは、分岐最適化のためにオブジェクトを導入できません。分岐最適化のために 2 次元配列 を導入できます:
function getUserDescribe(name) { const describeForNameMap = [ [ (name) => name.length > 3, // 判断条件 () => console.log("名字太长") // 执行函数 ], [ (name) => name.length < 2, () => console.log("名字太短") ], [ (name) => name[0] === "陈", () => console.log("小陈") ], [ (name) => name === "大鹏", () => console.log("管理员") ], [ (name) => name[0] === "李" && name !== "李鹏", () => console.log("小李"), ], ]; // 获取符合条件的子数组 const getDescribe = describeForNameMap.find((item) => item[0](name)); // 子数组存在则运行子数组中的第二个元素(执行函数) getDescribe ? getDescribe[1]() : console.log("此人比较神秘!"); }
上記では、describeForNameMap
配列を定義しました。配列内の各要素は、一連の判定条件と実行関数 (これも配列) を表します。その後、配列の find
メソッドを使用します。 describeForNameMap
配列内で判定条件を満たす部分配列を見つけます。
上の例で定義した describeForNameMap
オブジェクトは独立した構造であり、完全に切り離すことができます。
const describeForNameMap = { 小刘: () => console.log("刘哥哥"), 小红: () => console.log("小红妹妹"), 陈龙: () => console.log("大师"), 李龙: () => console.log("师傅"), 大鹏: () => console.log("恶人"), }; function getUserDescribe(name) { describeForNameMap[name] ? describeForNameMap[name]() : console.log("此人比较神秘!"); }
const describeForNameMap = [ [ (name) => name.length > 3, // 判断条件 () => console.log("名字太长") // 执行函数 ], [ (name) => name.length < 2, () => console.log("名字太短") ], [ (name) => name[0] === "陈", () => console.log("小陈") ], [ (name) => name === "大鹏", () => console.log("管理员") ], [ (name) => name[0] === "李" && name !== "李鹏", () => console.log("小李"), ], ]; function getUserDescribe(name) { // 获取符合条件的子数组 const getDescribe = describeForNameMap.find((item) => item[0](name)); // 子数组存在则运行子数组中的第二个元素(执行函数) getDescribe ? getDescribe[1]() : console.log("此人比较神秘!"); }
モジュール開発を通じて、この
map
オブジェクトを別のjs
ファイルに記述し、それを使用する必要がある場所にインポートすることもできます。それでおしまい。
このようにして、getUserDescribe
関数全体が非常に簡潔になります。これに何の意味があるのかと尋ねる学生もいるかもしれません。 ?何を使うか?こっちの方が面倒じゃないですか? if else
が本当に適切ではない場合は、else
の代わりに if return
を使用します。
function getUserDescribe(name) { if (name === "小刘") { console.log("刘哥哥"); return; } if (name === "小红") { console.log("小红妹妹"); return; } if (name === "陈龙") { console.log("大师"); return; } if (name === "李龙") { console.log("师傅"); return; } if (name === "大鹏") { console.log("恶人"); return; } console.log("此人比较神秘!"); }
想像してみてください。 getUserDescribe
関数には1000の判定分岐があり、判定結果に基づいて実行される処理コードも多数あり、getUserDescribe
関数はこの値を返します。処理された判定結果。
このとき、getUserDescribe
関数の focus は、どの分岐で結果が得られるかではなく、 判定結果の処理にあります。例:
function getUserDescribe(name) { let str; // 存储判断结果 if (name.length > 3) { str = "名字太长"; } else if (name.length < 2) { str = "名字太短"; } else if (name[0] === "陈") { str = "小陈"; } else if (name[0] === "李" && name !== "李鹏") { str = "小李"; } else if (name === "李鹏") { str = "管理员"; } else { str = "此人比较神秘!"; } // 对判断结果str的一些处理 // ...... console.log(str); return str; }
getUserDescribe 関数は多数の
if ブランチによって占有され、
getUserDescribe Lost の関数に焦点を当てます (
getUserDescribeFunction
焦点は判定結果の処理です。 結果がどのブランチを通じて得られるかではありません)。最適化されたコード:
const describeForNameMap = [ [(name) => name.length > 3, () => "名字太长"], [(name) => name.length < 2, () => "名字太短"], [(name) => name[0] === "陈", () => "小陈"], [(name) => name === "大鹏", () => "管理员"], [(name) => name[0] === "李" && name !== "李鹏", () => "小李"], ]; function getUserDescribe(name) { let str; // 存储判断结果 const getDescribe = describeForNameMap.find((item) => item[0](name)); if (getDescribe) { str = getDescribe[1](); } else { str = "此人比较神秘!"; } // 对判断结果str的一些处理 // ...... console.log(str); return str; }
getUserDescribe 関数を見ると、
describeForNameMap から値を取得し、それを
str## に割り当てていることがわかります。 # (describeForNameMap
が値をどのように返すかは気にしません) で、str
に対して何らかの処理を行いました。これは、getUserDescribe
関数 (判定結果 str
の処理) の焦点を強調表示します。
describeForNameMapサブ配列の 2 番目の要素で値を直接使用できます:
[(name) => name.length > 3 , "Nameは長すぎます"]
ただし、コード全体のスケーラビリティを考慮すると、関数を使用することをお勧めします。関数はパラメーターを受け取ることができるため、将来的により複雑なシナリオに対処しやすくなります。
ブランチの最適化さまざまな言語でさまざまな実装方法とアプリケーション シナリオが存在します。この記事では JavaScript
を使用します。コード ブランチの最適化に関する 2 つのアイデアを紹介します。コードの実装は非常にシンプルで、このアイデアの適用に重点が置かれています。
実は、ブランチの最適化の問題については議論があり、現在 2 つのビューがあります:
オブジェクト/配列
を作成するため、 オブジェクト/配列
を取得することは、単純に if else
を実行するよりもさらに無駄です。 可読性/保守性
は向上しており、object/array
の導入によりパフォーマンスの問題が発生します。この時代では言及する価値はありません。 #########あなたの意見は何ですか? プログラミング教育
をご覧ください。 !以上がある記事では、分岐最適化の場合に JavaScript を実装する方法を説明しています。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。