Есть ли разница между foreach и map?

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

8 ответов


разные.

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

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


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


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

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

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

    map, С другой стороны, имеет ограничение на операцию: он ожидает, что операция вернет элемент и, вероятно, также примет элемент в качестве аргумента. The map операция выполняет итерацию над коллекцией элементов, применяя операцию к каждому элементу и, наконец, сохраняя результат каждого вызова операции в другие коллекции. Другими словами,map преобразование одной коллекции в другую.

  2. foreach работает с одной коллекцией элементов. Это коллекция входных данных.

    map работает с двумя коллекциями элементов: входной коллекцией и выходной коллекцией.

это не ошибка, чтобы связать два алгоритма: на самом деле, вы можете просматривать два иерархически, где map это специализация foreach. То есть, вы могли бы использовать foreach и операция преобразует свой аргумент и вставляет его в другую коллекцию. Итак,foreach алгоритм является абстракцией, обобщением . На самом деле, потому что foreach не имеет никаких ограничений на его работу мы можем смело сказать, что foreach Это самый простой механизм зацикливания, и он может делать все, что может сделать цикл. map, а также другие более специализированные алгоритмы существуют для выразительности: если вы хотите отобразить (или преобразовать) одну коллекцию в другую, ваше намерение будет более ясным, если вы используете map чем если вы используете foreach.

мы можем продолжить эту дискуссию дальше и рассмотреть copy алгоритм: цикл, который клонирует коллекцию. Этот алгоритм тоже является специализацией . Вы можете определить операцию, которая, учитывая элемент, вставит этот же элемент в другую коллекцию. Если вы используете 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));
});

они дают точный результат ditto.

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 выполняется только для самого выполнения.

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

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 by map, решение по-прежнему будет действительным. В решение 2, замена map by 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() это строгое супер-сет of 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 с использованием списков: карта возвращает список, foreach ничего не возвращает.

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

So 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 Если вы хотите do что-то на основе каждого элемента списка. Например, вы можете добавлять что-то на страницу. По существу, это отлично подходит, когда вы хотите "побочные эффекты".

другие отличия: forEach ничего не возвращает (поскольку это действительно функция потока управления), а переданная функция получает ссылки на индекс и весь список, тогда как map возвращает новый список и передает только текущий элемент.