2010-04-16 23 views
9

Ben Scala'nın Listeler imza (f: (A) => B):List[B] ile map uygulama ve imza (f: (A) => Unit):Unit ile foreach uygulaması olduğunu biliyorum ama birden Iterables Python map birden Iterables kabul ettiğini aynı şekilde kabul şey arıyorum.Scala'da Python'un daha genel harita fonksiyonuna denk mi var?

(f: (A,B) => C, Iterable[A], Iterable[B]):Iterable[C] imzası olan veya benzeri bir ürünü arıyorum. Bunun var olduğu bir kütüphane var mı, benzer mi?

Düzenleme:

val output = myList zip(otherList) map(x => x(0) + x(1)) 

yapabileceğini altında

önerildiği gibi ama bu adımlar arasında geçici bir liste oluşturur. Eğer yorumcu gönderirse onu yakabilirim (ipucu, ipucu) ama başka bir yol var mı?

+2

olarak adlandırılırsa, zip() işlevi çalışmıyorsa, farklı bir şekilde ne yapmanız gerekir? –

+0

oğlu ... zip. Tamamdır! Bunu düşünmemiştim bile. Neden yayınlamıyorsun ki, bunu yapabilirim. – wheaties

+4

Ben cevaplamak için @Mike'ı bırakacağım, ancak 'list1 zip list2' ve ayrıca' (list1, list2) .zipli 'yapabilirsin. İkincisi, sadece Scala 2.8, geçici bir koleksiyon oluşturmaz. Ayrıca, geçici koleksiyonlar oluşturmaktan kaçınmak için sırasıyla Scala 2.8 ve 2.7 üzerinde 'list1.view zip list2' veya' list1.projection zip list2' yapabilirsiniz. –

cevap

12

Scala 2.8'de geçici koleksiyon oluşturulmasını engelleyen Tuple2 & Tuple3'te sıkıştırılmış olarak adlandırılan bir yöntem vardır.

Welcome to Scala version 2.8.0.r21561-b20100414020114 (Java HotSpot(TM) Client VM, Java 1.6.0_18). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> val xs = 0 to 9 
xs: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 

scala> val ys = List.range(0,10) 
ys: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 

scala> val zs = Array.range(0,10) 
zs: Array[Int] = Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 

scala> (xs,ys).zipped.map{ _+_ } 
res1: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 2, 4, 6, 8, 10, 12, 14, 16, 18) 

scala> (zs,ys,xs).zipped.map{ _+_+_ } 
res2: Array[Int] = Array(0, 3, 6, 9, 12, 15, 18, 21, 24, 27) 

scala> 

Tuple2 ve Tuple3 hem de bir zip yöntemi vardır: İşte bazı örnek kullanıldığı durumdur. bazı sıkıntısı da vardır .zip ve (xs, ys) .zipped (xs, ys), emin olun: xs.zip (ys)

Not .zip (xs, ys) ile aynıdır xs bir INFINITE akışı olamaz. Daha fazla bilgi için Ticket #2634 adresine gidin. Birkaç gün önce nabble.com'da a post var, bu biletin nasıl düzeltileceğiyle ilgili görüşlerimi gösteriyor.

3

Scala 2.7'de List nesnesinde map2 yönteminin bir yöntemi vardır (ve 2.8, ancak zipped lehine kabul edilmez). Öyle gibi kullanın:

List.map2(List(1,2,3) , List(4,5,6)) { _ * _ } // Gives List(4,10,18) 

Eastsun zaten 2.8'de zipped nasıl kullanılacağı gösterilmiştir (bütün koleksiyonları çalışır Tabi bu sadece listeler).

+0

2.7 yorumuna minnettarım. Yakında 2.8'e geçiş yapacağım. – wheaties

2

Eh, sözdizimi (f: (A,B) => C, Iterable[A], Iterable[B]):Iterable[C] bilmiyorum (ve şey Scala biliyorum) ama sanırım olsaydı, o iki iterable savunmalarını alan f "Bir fonksiyonu anlamına geleceğini A ve B ve tekrarlanabilir bir C ". Bunun, tüm yinelenenlerin aynı sayıda ürünü verdiğine işaret edip etmediğinden emin değilim. Neyse

>>> A=range(10, 12) 
>>> zip(A, B) 
[(10, 1000), (11, 1100)] 

, bazı almanın doğasında:

>>> A = range(10, 15) 
>>> B = range(1000, 1500, 100) 
>>> zip(A, B) 
[(10, 1000), (11, 1100), (12, 1200), (13, 1300), (14, 1400)] 
>>> [a + b for a,b in zip(A, B)] 
[1010, 1111, 1212, 1313, 1414] 

zip 'ın çıkış kısa iterable sadece bu kadar uzun: Python

, sana zip işlevi aradığınız düşünüyorum Python işlevlerinde herkesin bilmesi gereken ama kolayca özlediği: enumerate, map, reduce ve zip.Bu listede filter vardı, ancak bu günlerde liste kavramak için daha net ve daha esnek.

11

Aradığınız işlev genellikle zipWith olarak adlandırılır. Maalesef standart kütüphanelerde sağlanan, ancak yazmak için oldukça kolay değil:

def zipWith[A,B,C](f: (A,B) => C, a: Iterable[A], b: Iterable[B]) = 
    new Iterable[C] { 
    def elements = (a.elements zip b.elements) map f.tupled 
    } 

Bu sadece bir kez üzerinden geçer, yineleyiciler üzerinde zip ve map için uygulamalar tamamen tembel olduğundan.

Ancak neden Iterable durur? Bunun daha genel bir formu var. Bu şekilde sıkıştırılabilen tüm veri yapıları için bir arayüz belirtebiliriz.

trait Zip[F[_]] { 
    def zipWith[A,B,C](f: (A,B) => C, a: F[A], b: F[B]): F[C] 
} 

Örneğin, işlevlerini zip: Bu tip daha da genel ifadesi olmalı çıkıyor

trait Reader[A] { 
    type Read[B] = (A => B) 
} 

def readerZip[T] = new Zip[Reader[T]#Read] { 
    def zipWith[A,B,C](f: (A,B) => C, a: T => A, b: T => B): T => C = 
    (t: T) => f(a(t),b(t)) 
} 

. Bu arayüz bir uygulanmasına izin genel yazın yapıcıları olarak applicative functors

trait Applicative[F[_]] { 
    def pure[A](a: A): F[A] 
    def map[A,B](f: A => B, a: F[A]): F[B] 
    def ap[A,B](f: F[A => B], a: F[A]): F[B] 
} 

zipWith bir uygulama daha sonra olduğu gibi bu:

Bu, herhangi bir Arity işlevleriyle genelleştirir
def zipWith[F[_],A,B,C](f: A => B => C, a: F[A], b: F[B]) 
         (implicit m: Applicative[F]) = 
    m.ap(m.map(f,a), b) 

:

m.ap(m.ap(m.ap(m.map(f,a), b), c), d) 

Scalaz kitaplığı, standart kitaplıktaki birçok veri yapısı için Uygulamalı örnekler sağlar. Ayrıca, ap için uygun sözdizimi sağlanmıştır. Scalaz'da, bu işlev <*>:

def zipWith[F[_]:Applicative,A,B,C](f: A => B => C, a: F[A], b: F[B]) = 
    (a map f) <*> b 
+0

Teşekkür ederim. Öğrenecek çok şeyim var. Bu çok eğitici oldu. – wheaties

İlgili konular