JS での Reduce Fold Unfold の使用法の詳細な説明

JS での Reduce Fold Unfold の使用法の詳細な説明

折りたたむ(減らす)

では、reduce についてお話しましょう。私はこの関数がとても気に入っています。この関数は、多くのコードを節約し、宣言的なプロトタイプをいくつか備えています。flatten、deepCopy、mergeDeep などの一般的なツール関数は、reduce を使用してエレガントかつ簡潔に実装されています。 Reduceはfoldとも呼ばれます。基本的には配列を折りたたむプロセスです。計算によって配列内の複数の値を1つの値に変換します。各計算は関数によって処理されます。この関数はreducerと呼ばれるreduceのコア要素です。reducer関数は、単一の値を返す2次元関数です。一般的なadd関数はreducerです。

const addReducer = (x, y) => x + y;

add 関数はリデューサーです。最も一般的な使用法は、配列の Reduce メソッドと組み合わせて使用​​することです。

[1, 2, 3, 4, 5].reduce(addReducer, 0) // 15

Reduce をよりよく理解するために、さまざまなアイデアを使用してこの関数を実装してみましょう。

for...of の使用

定数reduce = (f, init, arr) => {
  acc = init; とします。
  for (arrのconst項目) {
    acc = f(acc, アイテム);
  }
  返品
}
// 実行reduceFor(addReducer, 0, [1, 2, 3, 4, 5]) // 15

whileループの使用

減らす = (f, init, arr) => {
  acc = init; とします。
  電流を流す;
  i = 0 とします。
  while ((current = arr[i++])) {
    acc = f(acc, 現在の値);
  }
  acc を返します。
}

// 実行reduceFor(addReducer, 0, [1, 2, 3, 4, 5]) // 15

折り畳み実装に近い

上記の実装は理解しやすいですが、折り畳みプロセスを反映していないようです。折り畳みは、配列をレイヤーごとに圧縮する操作である必要があります。上記の実装では、実際には配列とロジックが分離され、内部的には副作用はありませんが、中間変数もさらに導入されています。
実は、別の観点から考えると、パラメータを介して状態を渡すと、フォールドプロセスをよりよく反映できます。ここでのパラメータは、徐々に変化する配列や計算値を参照する値であり、可能な限り状態を持たないようにすることができます。真に純粋な関数の実装には式はなく、ステートメントのみがあり、これは再帰で実現できます。以下の実装では末尾再帰を使用してreduceを実装しています。実装の過程で配列や計算値がどのように変化するかがわかります。折り畳みという名前にぴったりです

関数reduce(f, init, arr) {
  (arr.length === 0) の場合は init を返します。
  const [head, ...rest] = arr;
  戻り値:reduceRecursion(f, f(init, head), rest);
}

// 実行reduceFor(addReducer, 0, [1, 2, 3, 4, 5]) // 15

展開する

fold の逆は unfold です。名前が示すように、unfold は逆リデューサーに基づいて一連の値を生成します。この時点で、元のリデューサーの実装が (a, b) -> c に似ている場合、その逆は c -> [a, b] になります。シーケンスの生成は非常に基本的な操作ですが、この基本的な操作にも多くの実装のアイデアがあります。unfold を紹介する前に、シーケンスを実装する他の方法を見て比較してみましょう。

シーケンスの実装

範囲(0, 100, 5)

期待される結果

[0、5、10、... 95]

配列の実装

これについてはあまり言いませんが、誰もが知っているはずです。

範囲 = (最初、最後、ステップ) => {
  定数 n = (最後 - 最初) / ステップ + 1;
  Array.from({ 長さ: n - 1 }) を返します
            .map((_, index) => 最初 + インデックス * ステップ);
}
// from の 2 番目のパラメータを使用することもできます // Array.from({ length: n }, (_, i) => first + i * step);

ジェネレータの実装

シーケンスを生成するためのもう 1 つの強力なツールとして、データを生成するために使用されるジェネレーターがあります。ジェネレータはイテレータを返す。これも簡単にシーケンスを生成することができる。

関数*範囲(最初、最後、ステップ) {
  acc = first とします。
  while (acc < last) {
    収益 acc;
    acc = acc + ステップ;
  }
}
[...範囲(0, 100, 5)]

これら 2 つを比較すると、ジェネレーターは生成プロセスに重点を置いているのに対し、配列はデータ変更プロセスに重点を置いています。

実装を展開する

unfold を実装する前に、まず実装のアイデアを整理しましょう。fold と同様に、これも再帰を使用し、実装プロセス中に対応するデータの変更を確認する必要があります。一般的なプロセスは次のとおりです。

0 -> [0, 5]

5 -> [5, 10]

10 -> [10, 15]

15 -> [15, 20]

...

90 -> [90, 95]

95 -> [95, 100]

このプロセスは、c -> [a, b] に準拠する fold の逆であることがわかります。初期値は配列である必要があるため、unfold には 2 つのパラメーターのみが必要であり、次のように実装されます。

関数展開(f, init) {
  定数 g = (f, next, acc) => {
    定数結果 = f(next);
    const [head, last] = 結果 || [];
    コンソールログ(最後);
    結果を返します? g(f, last, acc.concat(head)): acc;
  };
  g(f, init, []) を返します。
}

範囲 = R.curry((最初、最後、ステップ) =>
  展開(次 => 次 < 最後 && [次, 次 + ステップ], 0)
)

// 範囲(0, 100, 5)を実行する

要約する

上記は、FP プログラミングにおける非常に重要な 2 つの概念である fold と unfold の簡単な紹介であり、reduce と組み合わせてシーケンスを生成する例です。もちろん、これらの機能はシーケンスを生成するだけでなく、多くの強力な機能も備えています。

以上がJSにおけるreduce fold unfoldの使い方の詳しい説明です。JSについてさらに詳しく知りたい方は、123WORDPRESS.COMの関連記事もぜひご覧ください!

以下もご興味があるかもしれません:
  • JS での Reduce() メソッドの使用の概要
  • jsはreduceメソッドを使用してコードをよりエレガントにします
  • JavaScript 配列の Reduce() メソッドの構文と例の分析
  • JavaScript 配列の include と Reduce の基本的な使用法
  • js配列のfind、some、filter、reduceの違いの詳細な説明
  • 知っておくべき JS 配列削減の高度な使い方 25 選
  • JSはreduce()メソッドを使用してツリー構造データを処理します
  • JavaScript Reduceの詳しい説明
  • JavaScript Array.reduce ソースコードの詳細な説明
  • 8 JSのreduce使用例とreduce操作方法

<<:  Ubuntu にグラフィック ドライバーが正常にインストールされたかどうかを確認する方法

>>:  phpstudy から Linux への MySQL の移行に関するチュートリアル

推薦する

Springboot アプリケーションを迅速にデプロイするために Docker とアイデアを統合する詳細なプロセス

目次1. はじめに2. 環境とツール3. Dockerをインストールし、リモート接続を構成する4. ...

CSS3 でテキストの点滅効果を実現する 3 つの方法 サンプルコード

1. 透明度を変更してテキストを徐々に点滅させると、次のような効果が得られます。 <!DOCT...

Windows での MySQL 5.7.20 のインストールと設定方法のグラフィック チュートリアル

参考までにWindowsにMySQLをインストールします。具体的な内容は次のとおりです。 1.まずM...

Linux で削除できないファイル/フォルダの解決方法

序文最近、弊社のサーバーがハッカーの攻撃を受け、一部のファイルの属性が変更されたため、ウイルスファイ...

Dockerボリュームコンテナ間のデータ共有の実装

ボリュームとは何ですか?ボリュームは英語で容量を意味し、Docker ではデータ ボリューム、つまり...

MySQL 外部キー制約の詳細な説明

公式ドキュメント: https://dev.mysql.com/doc/refman/5.7/en/...

MySQLはカバーインデックスを使用してテーブルリターンを回避し、クエリを最適化します。

序文カバーリング インデックスについて説明する前に、まずそのデータ構造である B+ ツリーを理解する...

仮想マシンに Linux rhel7.3 オペレーティング システムをインストールする (具体的な手順)

仮想化ソフトウェアをインストールする仮想マシンにオペレーティング システムをインストールする前に、ホ...

1 つの記事で Node.js の非同期プログラミングを学ぶ

目次 はじめに 同期 非同期とブロッキング JavaScript のノンブロッキング コールバック ...

MySQL パスワード変更方法の概要

MySQL 5.7 より前のバージョンのパスワードを変更する方法:方法1: SET PASSWORD...

Nginx リバース プロキシから go-fastdfs へのケースの説明

背景go-fastdfs は、http プロトコルをサポートする分散ファイルシステムです。一般的なプ...

CSS マルチカラムレイアウトソリューション

1. 固定幅+適応型期待される効果: 左側は固定幅、右側は適応幅 共通コード: html: <...

Linux での Python スクリプトの自動起動とスケジュール起動の詳細な手順

1. Pythonは起動時に自動的に実行されますPython の自己起動スクリプトがauto.pyで...

Mysql を 5.7 にアップグレードした後のグループ クエリの問題を解決する

問題を見つける最近MySQLをMySQL 5.7にアップグレードした後、次のようなクエリでグループ化...

Linux での MySQL マルチインスタンスの展開とインストール ガイド

MySQLマルチインスタンスとは簡単に言うと、MySQL マルチインスタンスとは、サーバー上で複数の...