Ok, jest to raczej pytanie informatyczne niż pytanie oparte na konkretnym języku, ale czy istnieje różnica między operacją mapowania a operacją foreach? A może są to po prostu różne nazwy dla tej samej rzeczy?
Ok, jest to raczej pytanie informatyczne niż pytanie oparte na konkretnym języku, ale czy istnieje różnica między operacją mapowania a operacją foreach? A może są to po prostu różne nazwy dla tej samej rzeczy?
Odpowiedzi:
Różne.
foreach wykonuje iterację po liście i stosuje pewne operacje z efektami ubocznymi do każdego członka listy (na przykład zapisując każdego z nich w bazie danych)
map iteruje listę, przekształca każdy element tej listy i zwraca kolejną listę o tym samym rozmiarze z transformowanymi elementami (np. konwersję listy ciągów na wielkie litery)
map
ma nie doprowadzić do realizacji swojej podstawowej logiki aż po przekształcona lista spodziewane jest wezwany. Natomiast foreach
operacja jest obliczana natychmiast.
Ważna różnica między nimi polega na tym, że map
kumuluje wszystkie wyniki w kolekcji, a foreach
nic nie zwraca. map
jest zwykle używany, gdy chcesz przekształcić zbiór elementów za pomocą funkcji, podczas gdy foreach
po prostu wykonuje akcję dla każdego elementu.
W skrócie, foreach
służy do zastosowania operacji na każdym elemencie zbioru elementów, podczas gdy map
służy do przekształcenia jednej kolekcji w drugą.
Istnieją dwie znaczące różnice między foreach
i map
.
foreach
nie ma pojęciowych ograniczeń dotyczących stosowanej operacji, poza tym, że może przyjąć element jako argument. Oznacza to, że operacja może nic nie robić, może mieć efekt uboczny, może zwrócić wartość lub może nie zwrócić wartości. Wszystkie foreach
dba o to, aby iteracyjne nad zbiór elementów i zastosować operację na każdym elemencie.
map
z drugiej strony ma ograniczenie operacji: oczekuje, że operacja zwróci element i prawdopodobnie również zaakceptuje element jako argument. map
Działanie iteracje przez zbiór elementów, stosowanie operacji na każdym elemencie i na koniec przechowywanie wyniku każdego wywołania działania do innego zbioru. Innymi słowy, map
przekształca jedną kolekcję w drugą.
foreach
współpracuje z pojedynczą kolekcją elementów. To jest kolekcja danych wejściowych.
map
współpracuje z dwoma kolekcjami elementów: kolekcją wejściową i kolekcją wyjściową.
Odwoływanie się do dwóch algorytmów nie jest błędem: w rzeczywistości można je zobaczyć hierarchicznie, gdzie map
jest specjalizacja foreach
. Oznacza to, że możesz użyć foreach
operacji i przekształcić jej argument i wstawić go do innej kolekcji. Tak więc, foreach
algorytm jest abstrakcją, uogólnienie, z map
algorytmu. W rzeczywistości, ponieważ foreach
nie ma ograniczeń w jego działaniu, możemy śmiało powiedzieć, że foreach
jest to najprostszy dostępny mechanizm zapętlania i może on wykonywać wszystko, co może zrobić pętla. map
, podobnie jak inne bardziej wyspecjalizowane algorytmy, służy ekspresji: jeśli chcesz zmapować (lub przekształcić) jedną kolekcję w inną, twoja intencja jest wyraźniejsza, jeśli używasz, map
niż używasz foreach
.
Możemy rozszerzyć tę dyskusję i rozważyć copy
algorytm: pętlę, która klonuje kolekcję. Ten algorytm też jest specjalizacją foreach
algorytmu. Możesz zdefiniować operację, która przy danym elemencie wstawi ten sam element do innej kolekcji. Jeśli korzystasz foreach
z tej operacji, w rzeczywistości wykonałeś copy
algorytm, choć ze zmniejszoną jasnością, ekspresją lub wyraźnością. Przejdźmy jeszcze dalej: możemy powiedzieć, że map
jest to specjalizacja copy
sama w sobie foreach
. map
może zmienić dowolny z iterowanych elementów. Jeśli map
nie zmienia żadnego z elementów, to po prostu skopiował elementy i używał kopiowania wyraźniej wyraziłby to zamiar.
Sam foreach
algorytm może, ale nie musi, mieć wartość zwracaną, w zależności od języka. Na przykład w C ++ foreach
zwraca pierwotnie otrzymaną operację. Chodzi o to, że operacja może mieć stan i możesz chcieć, aby ta operacja wróciła, aby sprawdzić, jak ewoluowała nad elementami. map
, również może, ale nie musi, zwrócić wartość. W C ++ transform
(odpowiednik map
tutaj) zdarza się, że zwraca iterator na końcu kontenera wyjściowego (kolekcji). W Ruby zwracaną wartością map
jest sekwencja wyjściowa (kolekcja). Zatem zwracana wartość algorytmów jest naprawdę szczegółem implementacji; ich efekt może, ale nie musi, być tym, co zwracają.
.forEach()
można .map()
znaleźć tutaj: stackoverflow.com/a/39159854/1524693
Array.protototype.map
metoda i Array.protototype.forEach
oba są dość podobne.Uruchom następujący kod: 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));
});
Dają dokładny wynik 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
Tutaj po prostu przypisałem wynik wartości zwracanej z mapy i metod 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();
Teraz wynik jest trudny!
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
zwraca tablicę, ale Array.prototype.forEach
nie. Możesz więc manipulować zwróconą tablicą wewnątrz funkcji wywołania zwrotnego przekazanej do metody map, a następnie zwrócić ją.
Array.prototype.forEach
tylko przechodzi przez podaną tablicę, więc możesz robić swoje rzeczy podczas chodzenia po tablicy.
najbardziej „widoczną” różnicą jest to, że mapa akumuluje wynik w nowej kolekcji, podczas gdy foreach jest wykonywany tylko dla samego wykonania.
ale istnieje kilka dodatkowych założeń: ponieważ „celem” mapy jest nowa lista wartości, tak naprawdę nie ma znaczenia kolejność wykonywania. w rzeczywistości niektóre środowiska wykonawcze generują kod równoległy, a nawet wprowadzają pewne zapamiętywanie, aby uniknąć wywoływania powtarzających się wartości lub lenistwa, aby w ogóle nie wywoływać niektórych.
foreach, z drugiej strony, jest nazywany specjalnie dla skutków ubocznych; dlatego kolejność jest ważna i zwykle nie można jej sparaliżować.
Krótka odpowiedź: map
i forEach
są różne. Ponadto, mówiąc nieformalnie, map
jest to ścisły nadzór forEach
.
Długa odpowiedź: najpierw wymyślmy opisy jednej linii forEach
i map
:
forEach
iteruje wszystkie elementy, wywołując dostarczoną funkcję na każdym z nich.map
iteruje wszystkie elementy, wywołując podaną funkcję na każdym z nich, i tworzy transformowaną tablicę zapamiętując wynik każdego wywołania funkcji.W wielu językach forEach
jest często nazywany po prostu each
. Poniższa dyskusja używa JavaScript tylko w celach informacyjnych. To może być naprawdę dowolny inny język.
Teraz użyjmy każdej z tych funkcji.
forEach
:Zadanie 1: Napisz funkcję printSquares
, która akceptuje tablicę liczb arr
i drukuje w niej kwadrat każdego elementu.
Rozwiązanie 1:
var printSquares = function (arr) {
arr.forEach(function (n) {
console.log(n * n);
});
};
map
:Zadanie 2: Napisz funkcję selfDot
, która akceptuje tablicę liczb arr
i zwraca tablicę, w której każdy element jest kwadratem odpowiedniego elementu w arr
.
Poza tym: tutaj, w slangu, próbujemy wyrównać tablicę wejściową. Formalnie rzecz biorąc, staramy się obliczyć sam produkt kropkowy.
Rozwiązanie 2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
map
nadzbiór forEach
?Możesz użyć map
do rozwiązania obu zadań, zadania 1 i zadania 2 . Nie można jednak użyć forEach
do rozwiązania zadania 2 .
W roztworze 1 , jeśli po prostu zastąpić forEach
przez map
roztwór będą nadal ważne. Jednak w rozwiązaniu 2 zastąpienie map
przez forEach
spowoduje uszkodzenie wcześniej działającego rozwiązania.
forEach
w zakresie map
:Innym sposobem uświadomienia sobie map
wyższości jest wdrożenie forEach
w kategoriach map
. Ponieważ jesteśmy dobrymi programistami, nie pozwolimy sobie na zanieczyszczenie przestrzeni nazw. Zadzwonimy do naszego forEach
, tylko each
.
Array.prototype.each = function (func) {
this.map(func);
};
Teraz, jeśli nie lubisz prototype
bzdur, proszę:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
forEach
ogóle istnieje?Odpowiedzią jest wydajność. Jeśli nie jesteś zainteresowany transformacją tablicy w inną tablicę, dlaczego powinieneś obliczyć transformowaną tablicę? Tylko rzucić to? Oczywiście nie! Jeśli nie chcesz transformacji, nie powinieneś jej przekształcać.
Tak więc chociaż mapę można wykorzystać do rozwiązania zadania 1 , prawdopodobnie nie powinna. Każdy bowiem jest do tego odpowiednim kandydatem.
Podczas gdy w większości zgadzają się z @madlep „s odpowiedzi, chciałbym podkreślić, że map()
jest to ścisłe super zestaw z forEach()
.
Tak, map()
zwykle służy do tworzenia nowej tablicy. Można go jednak również użyć do zmiany bieżącej tablicy.
Oto przykład:
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!!"]
W powyższym przykładzie a
został dogodnie ustawiony tak, że a[i] === i
dla i < a.length
. Mimo to pokazuje moc map()
.
Oto oficjalny opismap()
. Zauważ, że map()
może nawet zmienić tablicę, na której się nazywa! Grad map()
.
Mam nadzieję, że to pomogło.
Edytowano 10-lis-2015: Dodano opracowanie.
map
funkcję, ale nie forEach
; nie możesz po prostu nie użyć map
zamiast forEach
? Z drugiej strony, jeśli język miałby, forEach
ale nie map
, musiałbyś wdrożyć własny map
. Nie można po prostu użyć forEach
zamiast map
. Powiedz mi co myślisz.
Oto przykład w Scali z wykorzystaniem list: mapa zwraca listę, foreach nic nie zwraca.
def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit
Zatem mapa zwraca listę wynikającą z zastosowania funkcji f do każdego elementu listy:
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 po prostu stosuje się do każdego elementu:
scala> var sum = 0
sum: Int = 0
scala> list foreach (sum += _)
scala> sum
res2: Int = 6 // res1 is empty
Jeśli mówisz w szczególności o Javascript, różnica jest taka map
jest to funkcja pętli, podczas forEach
gdy iterator.
Posługiwać się map
gdy chcesz zastosować operację do każdego członka listy i uzyskać wyniki z powrotem jako nową listę, bez wpływu na oryginalną listę.
Użyj, forEach
kiedy chcesz zrobić coś na podstawie każdego elementu listy. Możesz na przykład dodawać elementy do strony. Zasadniczo jest to świetne, gdy chcesz uzyskać „skutki uboczne”.
Inne różnice: forEach
powraca nic (ponieważ jest to naprawdę funkcją przepływu sterowania), a przekazywana w funkcji staje się odniesienia do indeksu i całej listy, podczas gdy map Zwraca nową listę i przekazuje tylko w bieżącym elemencie.
ForEach próbuje zastosować funkcję, taką jak zapis do db itp. Na każdym elemencie RDD bez zwracania czegokolwiek.
Ale map()
stosuje pewną funkcję do elementów rdd i zwraca rdd. Więc kiedy uruchomisz poniższą metodę, nie zawiedzie ona na linii 3, ale podczas zbierania RDD po zastosowaniu Foreach nie powiedzie się i wyrzuci błąd, który mówi:
Plik „<stdin>”, wiersz 5, w <module>
AttributeError: Obiekt „NoneType” nie ma atrybutu „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]
odscala.io.Source.fromFile("/home/me/file").getLines()
i zastosuję się.foreach(s => ptintln(s))
do niego, zostanie wydrukowane dobrze, ale zaraz potem się opróżni. Jednocześnie, jeśli się.map(ptintln(_))
o to ubiegam - po prostu robi się pusty i nic nie jest drukowane.