Хорошо, это больше вопрос информатики, чем вопрос, основанный на конкретном языке, но есть ли разница между операцией отображения и операцией foreach? Или это просто разные имена для одной и той же вещи?
Хорошо, это больше вопрос информатики, чем вопрос, основанный на конкретном языке, но есть ли разница между операцией отображения и операцией foreach? Или это просто разные имена для одной и той же вещи?
Ответы:
Разные.
foreach выполняет итерацию по списку и применяет некоторые операции с побочными эффектами к каждому члену списка (например, сохранение каждого из них в базе данных)
Карта выполняет итерацию по списку, преобразует каждого члена этого списка и возвращает другой список того же размера с преобразованными элементами (например, преобразование списка строк в верхний регистр)
map
не делает , не приводит к исполнению лежащих в его основе логики , пока когда ожидаемый трансформируются список вызывается. В отличие от этого, foreach
операция вычисляется немедленно.
Важное различие между ними заключается в том, что map
все результаты накапливаются в коллекции, а foreach
ничего не возвращается. map
обычно используется, когда вы хотите преобразовать коллекцию элементов с помощью функции, тогда как foreach
просто выполняет действие для каждого элемента.
Короче говоря, foreach
для применения операции к каждому элементу коллекции элементов, а map
для преобразования одной коллекции в другую.
Есть два существенных различия между foreach
и map
.
foreach
не имеет концептуальных ограничений на операцию, которую он применяет, кроме, возможно, принятия элемента в качестве аргумента То есть операция может ничего не делать, может иметь побочный эффект, может возвращать значение или может не возвращать значение. Все, foreach
что нужно, - это перебрать коллекцию элементов и применить операцию к каждому элементу.
map
с другой стороны, имеет ограничение на операцию: она ожидает, что операция вернет элемент, и, вероятно, также примет элемент в качестве аргумента. map
Операции перебирает коллекцию элементов, применяя операцию на каждом элементе, и , наконец , сохранение результата каждого вызова операции в другой коллекции. Другими словами, map
превращает одну коллекцию в другую.
foreach
работает с одной коллекцией элементов. Это входная коллекция.
map
работает с двумя коллекциями элементов: входной набор и выходной набор.
Не является ошибкой связывать два алгоритма: на самом деле, вы можете рассматривать два иерархически, где map
есть специализация foreach
. То есть вы могли бы использовать foreach
эту операцию, чтобы преобразовать ее аргумент и вставить его в другую коллекцию. Таким образом, foreach
алгоритм является абстракцией, обобщением map
алгоритма. Фактически, поскольку foreach
он не имеет ограничений по своей работе, мы можем с уверенностью сказать, что foreach
это самый простой механизм зацикливания, и он может делать все, что может делать цикл. map
Как и другие более специализированные алгоритмы, есть для выразительности: если вы хотите отобразить (или преобразовать) одну коллекцию в другую, ваше намерение будет более ясным, если вы используете, map
чем если бы вы использовали foreach
.
Мы можем продолжить это обсуждение и рассмотреть copy
алгоритм: цикл, который клонирует коллекцию. Этот алгоритм тоже является специализацией foreach
алгоритма. Вы можете определить операцию, которая при наличии элемента будет вставлять этот же элемент в другую коллекцию. Если вы используете foreach
эту операцию, вы фактически выполняете copy
алгоритм, хотя и с меньшей ясностью, выразительностью или ясностью. Давайте сделаем это еще дальше: мы можем сказать, что map
это специализация copy
, сама специализацияforeach
. map
может изменить любой из элементов, которые он повторяет. Если map
не изменяет ни один из элементов, он просто копирует элементы и использует копию выразит намерение более четко.
Сам foreach
алгоритм может иметь или не иметь возвращаемое значение, в зависимости от языка. Например, foreach
в C ++ возвращает первоначально полученную операцию. Идея состоит в том, что операция может иметь состояние, и вы можете захотеть, чтобы эта операция вернулась, чтобы проверить, как она развивалась над элементами. map
тоже может возвращать или не возвращать значение. В C ++ transform
(здесь эквивалент map
) происходит возврат итератора в конец контейнера вывода (коллекции). В Ruby возвращаемое значение map
является выходной последовательностью (коллекцией). Таким образом, возвращаемое значение алгоритмов действительно является деталью реализации; их эффект может быть или не быть тем, что они возвращают.
.forEach()
можно использовать для реализации .map()
, см. Здесь: stackoverflow.com/a/39159854/1524693
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 выполняется только для самого выполнения.
но есть пара дополнительных предположений: поскольку «цель» карты - это новый список значений, на самом деле не имеет значения порядок выполнения. на самом деле, некоторые среды выполнения генерируют параллельный код или даже вводят некоторую запоминание, чтобы не вызывать повторяющиеся значения, или лень, чтобы вообще не вызывать некоторые.
foreach, с другой стороны, специально предназначен для побочных эффектов; поэтому порядок важен и обычно не может быть распараллелен.
Краткий ответ: map
и forEach
разные. Также, неофициально говоря, map
это строгий надмножество forEach
.
Длинный ответ: во- первых, давайте придумаем одну строку описания 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:
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()
.
Надеюсь, это помогло.
Отредактировано 10 ноября 2015: добавлена разработка.
map
функция, но нет forEach
; не могли бы вы просто не использовать map
вместо forEach
? С другой стороны, если у языка есть, forEach
но нет map
, вам придется реализовать свой собственный map
. Вы не могли бы просто использовать forEach
вместо map
. Скажи мне, что ты думаешь.
Вот пример использования Scala в 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 пытается применить функцию, такую как запись в db и т. Д., К каждому элементу СДР, не возвращая ничего обратно.
Но map()
применяется некоторая функция над элементами rdd и возвращает rdd. Поэтому, когда вы запустите приведенный ниже метод, он не завершится с ошибкой в строке 3, но при сборе rdd после применения foreach он завершится ошибкой и выдаст ошибку, которая говорит:
Файл "<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]
отscala.io.Source.fromFile("/home/me/file").getLines()
и применить.foreach(s => ptintln(s))
к нему, он печатается нормально , но пустеет сразу после. В то же время, если я обращаюсь.map(ptintln(_))
к нему - он просто становится пустым и ничего не печатается.