好吧,这更多的是一个计算机科学问题,而不是基于特定语言的问题,但是映射操作和 foreach 操作之间有区别吗?或者它们只是同一事物的不同名称?

有帮助吗?

解决方案

不同。

在一个列表上的foreach迭代,并且适用与副作用每个列表成员的一些操作(如保存每一个到数据库例如)

地图上一个列表上循环,转换该列表中的每个成员,并且返回与变换件(例如,当转换字符串为大写的列表)相同大小的另一列表

其他提示

它们之间的重要区别在于map积累所有结果到一个集合,而foreach没有返回。 map通常使用时要变换与功能元件的集合,而简单地foreach执行用于每个元件的操作。

简而言之, foreach 用于对元素集合中的每个元素应用操作,而 map 用于将一个集合转换为另一个集合。

之间有两个显着差异 foreachmap.

  1. foreach 除了可能接受一个元素作为参数之外,对其应用的操作没有概念上的限制。也就是说,该操作可能不执行任何操作,可能有副作用,可能返回值或可能不返回值。全部 foreach 关心的是迭代元素集合,并对每个元素应用操作。

    map, 另一方面,确实对操作有限制:它期望操作返回一个元素,并且可能还接受一个元素作为参数。这 map 操作迭代元素集合,对每个元素应用操作,最后将每次调用操作的结果存储到另一个集合中。换句话说, map 转变 将一个集合放入另一个集合中。

  2. foreach 适用于单个元素集合。这是输入集合。

    map 适用于两个元素集合:输入集合和输出集合。

将这两种算法联系起来并没有错:事实上,您可以按层次结构查看两者,其中 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没有。这样你就可以操纵传递给地图方法,然后回调函数内返回的数组返回它。

Array.prototype.forEach只能通过给定的数组,所以你可以做你的东西边走边阵列散步。

最“可见的”不同的是,图累积结果在一个新的集合,而的foreach是为执行本身只进行。

但也有一些额外的假设:由于地图的“目的”是价值的新的列表,它并不真正重要的执行顺序。事实上,一些执行环境生成并行代码,或者甚至引入一些memoizing避免调用重复值,或者lazyness,避免调用一些在所有。

的foreach,在另一方面,是专门为副作用调用;因此顺序是重要的,并且通常不能被并行化。

简短回答: mapforEach 是不同的。另外,非正式地说, map 是一个严格的超集 forEach.

长答案: 首先,让我们给出一行描述 forEachmap:

  • forEach 迭代所有元素,对每个元素调用提供的函数。
  • map 迭代所有元素,对每个元素调用提供的函数,并通过记住每个函数调用的结果来生成转换后的数组。

在许多语言中, forEach 通常被称为只是 each. 。以下讨论使用 JavaScript 仅供参考。它实际上可以是任何其他语言。

现在,让我们使用这些函数。

使用 forEach:

任务1: 写一个函数 printSquares, ,它接受数字数组 arr, ,并打印其中每个元素的平方。

解决方案一:

var printSquares = function (arr) {
    arr.forEach(function (n) {
        console.log(n * n);
    });
};

使用 map:

任务2: 写一个函数 selfDot, ,它接受数字数组 arr, ,并返回一个数组,其中每个元素是相应元素的平方 arr.

在旁边:在这里,用俚语来说,我们试图对输入数组进行平方。正式地说,我们正在尝试计算它与其自身的点积。

解决方案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 甚至存在?

答案是效率。如果您对将一个数组转换为另一个数组不感兴趣,为什么要计算转换后的数组?只能扔掉吗?当然不是!如果你不想转型,就不应该转型。

所以虽然map可以用来解决 任务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 日编辑:添加了详细说明。

下面是使用列表Scala中的一个示例:地图返回列表的foreach返回任何。

def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit

所以地图返回从施加所述函数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没有返回值(因为它是一个真正的控制流的功能),和传入的函数获得的索引和整个列表的引用,而地图返回新的列表,并且仅通过在当前元素。

的ForEach尝试应用的功能,例如不返回任何东西的RDD中的每个元素写入分贝等等。

map()适用过RDD的元素一些功能,并返回RDD。所以,当你运行下面的方法就不会在3号线失败,但同时应用的foreach之后收集RDD它会失败,并抛出它说

错误
  

文件 “<标准输入>”,第5行,在<模块>

     

AttributeError的: 'NoneType' 对象没有属性 '收集'

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())
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top