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 の移行に関するチュートリアル

推薦する

MySQL 5.5 のインストールと設定のグラフィックチュートリアル

MySQL 5.5 のインストールと構成のチュートリアル ノートを整理し、全員と共有します。 1.公...

Typescript の as、疑問符、感嘆符の詳細な説明

1. asキーワードはアサーションを示すTypescript では、アサーションを表現する方法が 2...

CentOS 7 で grub パスワードと単一ユーザー ログインを設定するサンプル コード

Centos7 と Centos6 では、GRUB パスワードの設定手順に大きな違いがあります。これ...

Tomcatの全体構造の簡単な紹介

Tomcat は Web コンテナとして広く知られています。Java を学び始めたときから現在の仕事...

Node.js における npx コマンドの使用法とシナリオ分析

npx 使用チュートリアル今晩、 Vue-Cli勉強していたところ、ふと最新の@4.xxバージョンを...

LinuxはMySQLデータベースの自動バックアップとスケジュールバックアップを毎日実装しています

概要バックアップは災害復旧の基礎であり、システム操作エラーやシステム障害によるデータ損失を防ぐために...

CSS3 のディスプレイのグリッドレイアウトとフレックスレイアウトの詳細な説明

Gird レイアウトは Flex レイアウトといくつかの類似点があり、どちらもコンテナーの内部項目を...

MySQL DDLステートメントの使用

序文SQL の言語分類には主に以下の種類があります。 DDLデータ定義言語作成、削除、変更データ定義...

MySQLテーブルのテーブル構造を素早く変更する方法

MySQL テーブルのテーブル構造をすばやく変更する - 「MySQL 管理」から抜粋 ALTER ...

Ubuntu 19にTheanoをインストールする際の問題を解決する

解決: pythearn2 パッケージをダウンロードしたディレクトリで、setup.py ファイルを...

Vue で Graphql インターフェースを実装する例

注意:この記事は現在取り組んでいる nestjs+graphql+serverless 合宿における...

MySQLの手順を完全に削除する

目次1. まずMySQLサーバーを停止する2. MySQLサーバーをアンインストールする3. MyS...

フラットスタイルを使用してウェブサイトをデザインする方法

フラットなウェブサイト構造の本質はシンプルさです。コンテンツの重要なポイントを強調し、ページの装飾効...

Windows 10 Home Edition に Docker for Windows をインストールする

0. 背景ハードウェア: Xiaomi Notebook Air 13/Inter Core i7-...

Vue でのルーティングガードの具体的な使用法

目次1. グローバルガード1.1 グローバルフロントガード1.2 グローバルポストルートガード1.3...