Tamam, bu bir bilgisayar bilimi sorusundan daha çok, belirli bir dile dayalı bir sorudan daha fazlasıdır, ancak bir harita işlemi ve bir foreach işlemi arasında bir fark var mıdır? Yoksa aynı şey için farklı isimler mi?
Tamam, bu bir bilgisayar bilimi sorusundan daha çok, belirli bir dile dayalı bir sorudan daha fazlasıdır, ancak bir harita işlemi ve bir foreach işlemi arasında bir fark var mıdır? Yoksa aynı şey için farklı isimler mi?
Yanıtlar:
Farklı.
foreach bir liste üzerinde yinelenir ve her liste üyesine yan etkiler içeren bir işlem uygular (örneğin her birini veritabanına kaydetmek gibi)
harita bir liste üzerinde yinelenir, bu listenin her bir üyesini dönüştürür ve dönüştürülen üyelerle aynı boyutta başka bir liste döndürür (bir dize listesini büyük harfe dönüştürme gibi)
map
mu değil beklenen dönüştürülmüş liste davet edilmesi durumunda dek altında yatan mantık yürütme ile sonuçlanır. Buna karşılık, foreach
operasyonu hemen hesaplanır.
Aralarındaki önemli fark, map
tüm sonuçları bir koleksiyonda biriktirirken, foreach
hiçbir şey döndürmez. map
genellikle bir işlev içeren bir öğe koleksiyonunu dönüştürmek istediğinizde kullanılırken, foreach
her öğe için bir eylem yürütür.
Kısacası, foreach
bir elemanlar koleksiyonunun her elemanına bir işlem uygulamak, bir koleksiyonu map
diğerine dönüştürmek içindir.
foreach
Ve arasında iki önemli fark vardır map
.
foreach
bir öğeyi bağımsız değişken olarak kabul etmekten başka, uyguladığı işlem üzerinde hiçbir kavramsal kısıtlamaya sahip değildir. Yani, işlem hiçbir şey yapamaz, bir yan etkiye sahip olabilir, bir değer döndürebilir veya bir değer döndürmeyebilir. Tek foreach
önemlisi, bir öğe koleksiyonu üzerinde yineleme yapmak ve işlemi her bir öğeye uygulamaktır.
map
, diğer taraftan, işlem üzerinde bir kısıtlama vardır: işlemin bir öğe döndürmesini bekler ve muhtemelen bir öğeyi bağımsız değişken olarak kabul eder. map
Bu işlem, her eleman üzerinde işlem uygulanarak, ve son olarak da başka bir koleksiyona içine operasyon her çağırma sonucunu depolamak, elemanların bir toplama yineler. Başka bir deyişle, map
dönüştüren başka bir bir koleksiyon.
foreach
tek bir eleman koleksiyonu ile çalışır. Bu girdi koleksiyonudur.
map
iki eleman koleksiyonuyla çalışır: giriş toplama ve çıkış toplama.
İki algoritmayı ilişkilendirmek bir hata değildir: aslında, ikisini hiyerarşik olarak görebilirsiniz, nerede map
uzmanlaştığı foreach
. Yani, foreach
işlemin argümanını dönüştürüp başka bir koleksiyona eklemesini sağlayabilirsiniz. Yani, foreach
algoritma algoritmanın bir soyutlaması, bir genellemesidir map
. Aslında, foreach
çalışmasıyla ilgili herhangi bir kısıtlama olmadığından foreach
, bunun en basit döngü mekanizması olduğunu güvenle söyleyebiliriz ve bir döngünün yapabileceği her şeyi yapabilir. map
, diğer daha özel algoritmaların yanı sıra, ifade için de var: bir koleksiyonu diğerine eşlemek (veya dönüştürmek) istiyorsanız, niyetiniz kullandığınızdan map
daha açıktır foreach
.
Bu tartışmayı daha da genişletebilir ve copy
algoritmayı düşünebiliriz : bir koleksiyonu klonlayan bir döngü. Bu algoritma da algoritmanın bir uzmanlığıdır foreach
. Bir öğe verildiğinde, aynı öğeyi başka bir koleksiyona ekleyecek bir işlem tanımlayabilirsiniz. Bu foreach
işlemle copy
kullanırsanız, daha az netlik, ifade veya açıklık olsa da, aslında algoritmayı gerçekleştirdiniz . Daha da ileri gidelim: Bunun map
bir uzmanlaşma olduğunu copy
, kendi uzmanlaştığını söyleyebiliriz foreach
. map
olabilir değiştirebilir elemanların herhangi bitti dolaşır. Eğer map
bu sadece o elemanların herhangi değişmez kopyalanan öğeleri ve kullanma kopyasını niyetini daha net ifade ederdi.
foreach
Algoritma kendisi ya da dile bağlı olarak bir geri dönüş değeri olabilir veya olmayabilir. Örneğin, C ++ ' foreach
da ilk aldığı işlemi döndürür. Fikir, operasyonun bir durumu olabileceği ve o operasyonun elemanlar üzerinde nasıl geliştiğini kontrol etmesini isteyebilirsiniz. map
de bir değer döndürebilir veya döndürmeyebilir. C ++ 'da transform
(bunun için eşdeğer map
) çıkış kabının (toplama) sonuna bir yineleyici döndürülür. Ruby, dönüş değeri map
çıktı dizi (toplama) 'dir. Yani, algoritmaların dönüş değeri gerçekten bir uygulama detayıdır; etkileri, geri döndükleri şey olabilir veya olmayabilir.
.forEach()
kullanılabileceğine ilişkin bir örnek .map()
için buraya bakın: stackoverflow.com/a/39159854/1524693
Array.protototype.map
yöntem ve Array.protototype.forEach
her ikisi de oldukça benzer.Aşağıdaki kodu çalıştırın: 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));
});
Kesin ditto sonucunu veriyorlar.
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
Burada haritadan dönüş değerinin sonucunu ve forEach yöntemlerini atadım.
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();
Şimdi sonuç zor bir şey!
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
bir dizi döndürür ancak Array.prototype.forEach
vermez. Böylece, döndürülen diziyi map yöntemine iletilen geri arama işlevi içinde değiştirebilir ve sonra geri verebilirsiniz.
Array.prototype.forEach
dizi yürürken malzeme yapabilirsiniz böylece sadece verilen dizi yürür.
en 'görünür' fark, haritanın yeni bir koleksiyonda sonucu biriktirmesi ve foreach yalnızca yürütmenin kendisi için yapılmasıdır.
ancak birkaç ekstra varsayım var: haritanın 'amacı' yeni değerler listesi olduğundan, yürütme sırası gerçekten önemli değildir. aslında, bazı yürütme ortamları paralel kod üretir, hatta bazılarını çağırmamak için tekrarlanan değerler veya tembellikten kaçınmak için bazı hatırlatmalar sunar.
Öte yandan foreach, özellikle yan etkiler için çağrılır; bu nedenle düzen önemlidir ve genellikle paralelleştirilemez.
Kısa cevap: map
ve forEach
farklı. Ayrıca, gayri resmi olarak, map
katı bir süper settir forEach
.
Uzun cevap: İlk olarak, biri hat açıklamaları ile gelip izin forEach
ve map
:
forEach
her öğede verilen işlevi çağırarak tüm öğeleri yineler.map
her öğede verilen işlevi çağırarak tüm öğeleri yineler ve her işlev çağrısının sonucunu hatırlayarak dönüştürülmüş bir dizi üretir.Birçok dilde, forEach
genellikle sadece denir each
. Aşağıdaki tartışma JavaScript'i yalnızca başvuru amacıyla kullanmaktadır. Gerçekten başka bir dil olabilir.
Şimdi bu işlevlerin her birini kullanalım.
forEach
:Görev 1: Bir printSquares
sayı dizisini kabul eden arr
ve içindeki her öğenin karesini yazdıran bir işlev yazın .
Çözüm 1:
var printSquares = function (arr) {
arr.forEach(function (n) {
console.log(n * n);
});
};
map
:Görev 2: Bir selfDot
sayı dizisini kabul eden arr
ve her öğenin karşılık gelen öğenin karesi olduğu bir dizi döndüren bir işlev yazın arr
.
Bir kenara: Burada argo terimlerle, girdi dizisini kareye almaya çalışıyoruz. Resmi olarak, nokta ürününü kendisi ile hesaplamaya çalışıyoruz.
Çözüm 2:
var selfDot = function (arr) {
return arr.map(function (n) {
return n * n;
});
};
map
Bir üst küme nasıl forEach
?Görev 1 ve Görev 2 gibimap
her iki görevi de çözmek için kullanabilirsiniz . Ancak, Görev 2'yi çözmek için kullanamazsınız .forEach
Gelen Çözüm 1 basitçe değiştirirseniz, forEach
tarafından map
, çözüm hala geçerli olacaktır. Gelen Çözüm 2 Ancak değiştirerek map
tarafından forEach
önceden çalışma çözümü kıracak.
forEach
açısından map
:Hayata bir başka yolu map
'ın üstünlüğünü uygulamaktır forEach
açısından map
. İyi programcılar olduğumuz için isim alanı kirliliğine kapılmayacağız. Biz forEach
sadece arayacağız each
.
Array.prototype.each = function (func) {
this.map(func);
};
Şimdi, prototype
saçmalıklardan hoşlanmıyorsanız , işte gidiyorsunuz:
var each = function (arr, func) {
arr.map(func); // Or map(arr, func);
};
forEach
bile?Cevap verimliliktir. Bir diziyi başka bir diziye dönüştürmek istemiyorsanız, dönüştürülen diziyi neden hesaplamalısınız? Sadece atmak için mi? Tabii ki değil! Bir dönüşüm istemiyorsanız, bir dönüşüm yapmamalısınız.
Harita Görev 1'i çözmek için kullanılabilse de , muhtemelen olmamalıdır. Her biri için doğru aday.
Ben büyük ölçüde @madlep 'ın cevabı ile kabul ederken, ben işaret etmek istiyorum map()
bir olan sıkı süper seti arasında forEach()
.
Evet, map()
genellikle yeni bir dizi oluşturmak için kullanılır. Bununla birlikte, olabilir , aynı zamanda , mevcut dizisini değiştirmek için kullanılabilir.
İşte bir örnek:
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!!"]
Yukarıdaki örnekte, a
uygun bir şekilde ayarlandı a[i] === i
için i < a.length
. Buna rağmen, gücünü gösterir map()
.
İşte resmi açıklamasımap()
. map()
Hatta denilen diziyi bile değiştirebileceğini unutmayın ! Dolu map()
.
Umarım bu yardımcı olmuştur.
Düzenlendi 10-Kasım-2015: Detaylandırma eklendi.
map
işlevi varsa ama hayır ise forEach
; map
bunun yerine kullanamaz mıydın forEach
? Flip tarafında, bir dil vardı forEach
ama hayır map
olsaydı, kendi dilinizi uygulamak zorunda kalacaksınız map
. Bunun forEach
yerine sadece kullanamazsınız map
. Bana ne düşündüğünü söyle.
İşte Scala'da listeleri kullanan bir örnek: map return list, foreach hiçbir şey döndürmez.
def map(f: Int ⇒ Int): List[Int]
def foreach(f: Int ⇒ Unit): Unit
Böylece harita, her liste öğesine f işlevinin uygulanmasından kaynaklanan listeyi döndürür:
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 her öğeye f uygular:
scala> var sum = 0
sum: Int = 0
scala> list foreach (sum += _)
scala> sum
res2: Int = 6 // res1 is empty
Özellikle Javascript hakkında konuşuyorsanız, fark bir yineleyici map
iken bir döngü işlevi forEach
olmasıdır.
map
Listenin her üyesine bir işlem uygulamak ve sonuçları orijinal listeyi etkilemeden yeni bir liste olarak almak istediğinizde kullanın .
Listenin her bir öğesi temelinde bir şeyler yapmakforEach
istediğinizde kullanın . Örneğin, sayfaya bir şeyler ekliyor olabilirsiniz. Temel olarak, "yan etkiler" istediğinizde mükemmeldir.
Diğer farklar: forEach
hiçbir şey döndürmez (gerçekten bir kontrol akışı işlevi olduğu için) ve aktarılan işlev dizine ve tüm listeye referans alırken, harita yeni listeyi döndürür ve yalnızca geçerli öğeye geçer.
ForEach, herhangi bir şey geri dönmeden RDD'nin her öğesinde db'ye yazma vb. Gibi bir işlevi uygulamaya çalışır.
Ancak map()
rdd öğelerine bazı işlevler uygular ve rdd değerini döndürür. Bu nedenle, aşağıdaki yöntemi çalıştırdığınızda, line3'te başarısız olmaz, ancak foreach uygulandıktan sonra rdd toplanırken başarısız olur ve bir hata atar.
<module> içindeki "<stdin>" dosyası, satır 5
AttributeError: 'NoneType' nesnesinin 'collect' özelliği yok
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]
alırscala.io.Source.fromFile("/home/me/file").getLines()
ve.foreach(s => ptintln(s))
ona başvurursam , tamam yazdırılır, ancak hemen sonra boşalır. Aynı zamanda.map(ptintln(_))
ona başvurursam - sadece boşalır ve hiçbir şey yazdırılmaz.