Вопрос

Хорошо, это скорее вопрос информатики, чем вопрос, основанный на определенном языке, но есть ли разница между операцией map и операцией foreach?Или это просто разные названия одной и той же вещи?

Это было полезно?

Решение

Другой.

foreach выполняет итерацию по списку и применяет некоторую операцию с побочными эффектами к каждому элементу списка (например, сохраняет каждый элемент в базе данных).

map выполняет итерацию по списку, преобразует каждый элемент этого списка и возвращает другой список того же размера с преобразованными элементами (например, преобразует список строк в верхний регистр).

Другие советы

Важное различие между ними заключается в том, что map накапливает все результаты в коллекцию, тогда как foreach ничего не возвращает. map обычно используется, когда вы хотите преобразовать коллекцию элементов с помощью функции, тогда как foreach просто выполняет действие для каждого элемента.

Короче говоря, foreach предназначен для применения операции к каждому элементу коллекции элементов, тогда как map предназначен для преобразования одной коллекции в другую.

Есть два существенных различия между foreach и map.

  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

Но поворот происходит, когда вы запускаете следующий код:-

Здесь я просто присвоил результат возвращаемого значения из методов map и 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 вызывается специально для побочных эффектов;поэтому порядок важен и обычно не может быть распараллелен.

Короткий ответ: 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 г.:Добавлена проработка.

Вот пример использования списков в 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 и т.д., К каждому элементу RDD, ничего не возвращая обратно.

Но тот map() применяет некоторую функцию к элементам rdd и возвращает rdd.Итак, когда вы запускаете приведенный ниже метод, он не завершится сбоем в строке 3, но при сборе rdd после применения foreach он завершится сбоем и выдаст ошибку, в которой говорится

Файл "<stdin>", строка 5, в <module>

Ошибка атрибута:Объект '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())
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top