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データベースはsysbenchに基づくOLTPベンチマークテストを実装します

Sysbench は、MySQL データベース ストレージ エンジン InnoDB のディスク I/...

JavaScript キャンバスはマウスの動きに合わせてボールを動かすことを実装します

この記事の例では、マウスに従ってボールを動かすjsの具体的なコードを参考までに共有しています。具体的...

js の hasOwnProperty のプロパティとインスタンスの使用法の詳細な説明

1. js は hasOwnProperty が不正に占有されることから保護しません。オブジェクトに...

Alibaba Cloud ESC に MYSQL8.0 をインストールするチュートリアル

接続ツールを開きます。私はMobaXterm_Personal_12.1を使用します(公式サイトのダ...

nginx 設定場所方法の概要

位置一致順序1. 「=」プレフィックス命令マッチング、マッチングが成功したら他のマッチングを停止2....

Vueコンポーネント間のデータ共有の詳細な説明

目次1. プロジェクト開発において、コンポーネント間の最も一般的な関係は次の 2 つのタイプに分けら...

YUM を使用して Linux (CentOS 7) に MySQL 5.7.18 をインストールする方法の詳細なチュートリアル

このプロジェクトでは MySQL を使用する必要があります。これまで Windows では常に確実に...

サーバーストレステストの概念と方法 (TPS/同時実行性)

目次1 ストレステストの指標1.1 秒あたり1.2 クォータ1.3 平均処理時間(RT) 1.4 同...

MySQL 8.0.12 のインストールと使用方法のチュートリアル

MySQL 8.0.12のインストールと使用のチュートリアルを録画しました。ウィンドウズまず、公式ウ...

MySql 範囲内の検索時にインデックスが有効にならない理由の分析

1 問題の説明この記事では、確立された複合インデックスをソートし、レコード内の非インデックス フィー...

ツールベースのウェブサイトの考察: ツールベースのウェブサイトの定義と典型的なケース分析 (写真とテキスト)

ツール型ウェブサイトについて、まず疑問に思うのは、無数のオンラインウェブサイトの中で、どのようなウェ...

コンパイル/サーバーなしでブラウザにCommonJSモジュールを実装する

目次導入1. one-click.jsとは2. パッケージングツールはどのように機能しますか? 3....

Linuxでkv設定ファイルを変更するにはsedコマンドを使用します

sed は Unix の文字ストリーム エディタ、つまりストリーム エディタです。行指向であり、行単...

HTML要素によるFlashブロックの詳細な例

コードをコピーコードは次のとおりです。 wmode パラメータ:透過モード: z-indexを使用し...

MySQLの自動増分主キーの実装の詳細な説明

目次1. 自己増分値はどこに保存されますか? 2. 自己価値修正メカニズム3. 自動増分値を変更する...