回答:
違う。
foreachはリストを反復処理し、副作用のある操作を各リストメンバーに適用します(それぞれをデータベースに保存するなど)
mapはリストを反復処理し、そのリストの各メンバーを変換し、変換されたメンバーと同じサイズの別のリストを返します(文字列のリストを大文字に変換するなど)
map
は、予期される変換済みリストが呼び出されるまで、その基礎となるロジックの実行にはなりません。対照的に、foreach
の操作はすぐに計算されます。
それらの間の重要な違いは、map
すべての結果をコレクションに蓄積する一方で、foreach
何も返さないことです。map
通常は、要素のコレクションを関数で変換するときに使用しますforeach
が、各要素に対してアクションを実行するだけです。
つまり、foreach
は要素のコレクションの各要素に操作を適用するためのものであり、一方のmap
コレクションを別のコレクションに変換するためのものです。
との間には2つの大きな違いがforeach
ありmap
ます。
foreach
要素を引数として受け入れる以外は、適用される操作に概念的な制限はありません。つまり、操作は何も実行しない、副作用がある、値を返す、または値を返さない場合があります。すべてforeach
気には要素のコレクションを反復処理し、各要素に対して操作を適用することです。
map
一方、操作には制限があります。操作は要素を返すことを期待しており、おそらく要素を引数として受け入れます。map
動作は、各要素に対して操作を適用して、要素のコレクションにわたって反復し、そして最後に別のコレクションに操作の各呼び出しの結果を格納します。つまり、あるコレクションを別のコレクションにmap
変換します。
foreach
要素の単一のコレクションで動作します。これは入力コレクションです。
map
要素の2つのコレクション(入力コレクションと出力コレクション)を操作します。
2つのアルゴリズムを関連付けることは間違いではありません。実際には、2つのアルゴリズムを階層的に表示できます。map
はの特殊化ですforeach
。つまりforeach
、引数を変換して使用し、別のコレクションに挿入することができます。したがって、foreach
アルゴリズムは、アルゴリズムの抽象化、一般化map
です。実際、foreach
その操作に制限がないため、これがforeach
最も単純なループメカニズムであり、ループが実行できるすべてのことを実行できます。map
、および他のより特殊なアルゴリズムは、表現力のためにあります。あるコレクションを別のコレクションにマップ(または変換)したい場合、を使用するmap
場合よりも使用する場合の方が明確ですforeach
。
この議論をさらに拡張して、copy
アルゴリズムを考えます。コレクションを複製するループです。このアルゴリズムもアルゴリズムの特殊化foreach
です。要素を指定して、その同じ要素を別のコレクションに挿入する操作を定義できます。foreach
その操作で使用する場合copy
、明快さ、表現力、または明示性は低下しますが、実際にはアルゴリズムを実行しました。さらに考えてみましょう。これmap
はの特殊化でありcopy
、それ自体がの特殊化ですforeach
。反復する要素を変更するmap
可能性があります。map
要素を変更しない場合は、単に要素をコピーし、コピーを 意図をより明確に表現します。
foreach
アルゴリズム自体はや言語に応じて、戻り値があってもなくてもよいです。たとえばC ++では、foreach
最初に受け取った操作を返します。アイデアは、操作に状態がある可能性があるということであり、その操作を元に戻して、要素上でどのように展開されたかを調べることができます。map
も、値を返す場合と返さない場合があります。C ++ transform
(map
ここでは同等)では、出力コンテナー(コレクション)の最後にイテレーターを返します。Rubyでは、の戻り値map
は出力シーケンス(コレクション)です。したがって、アルゴリズムの戻り値は実際には実装の詳細です。それらの効果は、それらが返すものである場合とそうでない場合があります。
Array.protototype.map
メソッド&Array.protototype.forEach
はどちらもかなり似ています。次のコードを実行します。http://labs.codecademy.com/bw1/6#:workspace
var arr = [1, 2, 3, 4, 5];
arr.map(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
});
console.log();
arr.forEach(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
});
彼らは正確な同上結果を与える。
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
ここでは、マップとforEachメソッドからの戻り値の結果を単に割り当てています。
var arr = [1, 2, 3, 4, 5];
var ar1 = arr.map(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
return val;
});
console.log();
console.log(ar1);
console.log();
var ar2 = arr.forEach(function(val, ind, arr){
console.log("arr[" + ind + "]: " + Math.pow(val,2));
return val;
});
console.log();
console.log(ar2);
console.log();
今、結果はトリッキーです!
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
[ 1, 2, 3, 4, 5 ]
arr[0]: 1
arr[1]: 4
arr[2]: 9
arr[3]: 16
arr[4]: 25
undefined
Array.prototype.map
配列を返しますが、返しArray.prototype.forEach
ません。そのため、mapメソッドに渡されたコールバック関数内で返された配列を操作して、それを返すことができます。
Array.prototype.forEach
与えられた配列のみをウォークスルーするので、配列をウォークしながら何かを行うことができます。
短い答え: map
とforEach
は異なります。また、非公式に言えば、map
の厳密なスーパーセットですforEach
。
長い答え:まず、聞かせてのはの1行の説明を思い付くforEach
とmap
:
forEach
すべての要素を反復処理し、それぞれの提供された関数を呼び出します。map
すべての要素を反復処理し、各要素で提供された関数を呼び出し、各関数呼び出しの結果を記憶することにより、変換された配列を生成します。多くの言語でforEach
は、しばしばと呼ばれますeach
。以下の説明では、参考のためにJavaScriptを使用しています。それは本当に他のどんな言語でもありえました。
それでは、これらの各関数を使用してみましょう。
forEach
:タスク1:printSquares
数値の配列を受け入れ、arr
その中の各要素の二乗を出力する関数を記述します。
解決策1:
var printSquares = function (arr) {
arr.forEach(function (n) {
console.log(n * n);
});
};
map
:タスク2:selfDot
数値の配列を受け入れ、arr
各要素がの対応する要素の二乗である配列を返す関数を記述しarr
ます。
余談:ここでは、俗語で、入力配列を2乗しようとしています。正式に言えば、それ自体のドット積を計算しようとしています。
解決策2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
map
スーパーセットはforEach
どうですか?を使用map
して、タスク1とタスク2の両方のタスクを解決できます。ただし、を使用forEach
してタスク2を解決することはできません。。
でソリューション1あなたは、単に交換する場合は、forEach
することによりmap
、解決策はまだ有効となります。で解決策2しかし、交換するmap
ことでは、forEach
あなたの前に作業溶液を中断します。
forEach
観点から実装map
:map
の優位性を実現する別の方法はforEach
、の観点から実装することですmap
。私たちは優れたプログラマーなので、名前空間の汚染にふけることはありません。私たちは、電話するよforEach
ただ、each
。
Array.prototype.each = function (func) {
this.map(func);
};
今、あなたがprototype
ナンセンスが好きではないなら、ここに行きます:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
forEach
存在するのですか?答えは効率です。配列を別の配列に変換することに関心がない場合、変換された配列を計算する必要があるのはなぜですか?それを捨てるだけですか?もちろん違います!変換が必要ない場合は、変換を実行しないでください。
したがって、マップはタスク1を解決するために使用できますが、おそらくそうすべきではありません。それぞれがそのための正しい候補です。
@madlepの答えにはほぼ同意しますが、これmap()
はの厳密なスーパーセットであることを指摘しておきforEach()
ます。
はい、map()
通常、新しいアレイを作成するために使用されます。ただし、現在の配列の変更にも使用できます。
次に例を示します。
var a = [0, 1, 2, 3, 4], b = null;
b = a.map(function (x) { a[x] = 'What!!'; return x*x; });
console.log(b); // logs [0, 1, 4, 9, 16]
console.log(a); // logs ["What!!", "What!!", "What!!", "What!!", "What!!"]
上記の例でa
は、はのように設定されてa[i] === i
いi < a.length
ます。それでも、の威力を発揮しmap()
ます。
の公式説明は次のとおりですmap()
。map()
それが呼ばれる配列を変更するかもしれないことに注意してください!雹map()
。
これがお役に立てば幸いです。
2015年11月10日編集:エラボレーションを追加。
map
関数があったが、ない場合forEach
。map
代わりに使用できませんでしたforEach
か?逆に言えば、ある言語にがありforEach
、ないmap
場合は、独自のを実装する必要がありますmap
。のforEach
代わりに単純に使用することはできませんmap
。あなたの考えを教えてください。
以下は、リストを使用したScalaの例です。mapはリストを返し、foreachは何も返しません。
def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit
したがって、mapは関数fを各リスト要素に適用した結果のリストを返します。
scala> val list = List(1, 2, 3)
list: List[Int] = List(1, 2, 3)
scala> list map (x => x * 2)
res0: List[Int] = List(2, 4, 6)
Foreachは単に各要素にfを適用します。
scala> var sum = 0
sum: Int = 0
scala> list foreach (sum += _)
scala> sum
res2: Int = 6 // res1 is empty
特にJavascriptについて話している場合、違いはmap
ループ関数ですが、forEach
がイテレータであるということです。
map
リストの各メンバーに操作を適用し、元のリストに影響を与えずに結果を新しいリストとして取得する場合に使用します。
リストの各要素に基づいて何かforEach
を実行したい場合に使用します。たとえば、ページに何かを追加する場合があります。基本的に、「副作用」が必要な場合に最適です。
その他の違い:(forEach
実際には制御フロー関数であるため)何も返しません。渡された関数はインデックスとリスト全体への参照を取得しますが、mapは新しいリストを返し、現在の要素のみを渡します。
ForEachは、何も返さずに、RDDの各要素にdbなどへの書き込みなどの関数を適用しようとします。
しかし、map()
はrddの要素に対していくつかの関数を適用し、rddを返します。したがって、以下のメソッドを実行すると、line3では失敗しませんが、foreachを適用した後にrddを収集している間は失敗し、次のエラーがスローされます
ファイル「<stdin>」、5行目、<module>
AttributeError: 'NoneType'オブジェクトには属性 'collect'がありません
nums = sc.parallelize([1,2,3,4,5,6,7,8,9,10])
num2 = nums.map(lambda x: x+2)
print ("num2",num2.collect())
num3 = nums.foreach(lambda x : x*x)
print ("num3",num3.collect())
Iterator[String]
from を取得しscala.io.Source.fromFile("/home/me/file").getLines()
て適用.foreach(s => ptintln(s))
した場合、それは問題なく出力されますが、直後は空になります。同時に私.map(ptintln(_))
がそれに適用する場合-それは単に空になり、何も印刷されません。