2013-03-22 17 views
5

Używam Scala 2.9, i chciałbym zbudować listę opartą na niektórych operacjach.Funkcjonalny styl mnożenia dwóch list ze Scala

Rozważmy następujący, mam dwóch prostych list:

 

    val l1 = List(2,3) 
    val l2 = List(List(4,5,6),List(7,8,9)) 

Zachowanie chcę jest następująca operacja z obu listach, tak:

 

    (2*4)+(3*7) 
    (2*5)+(3*8) 
    (2*6)+(3*9) 

I chciałbym w efekcie kolejna lista z tymi wartościami:

29,34,39

Już próbowałem rozwiązać za pomocą kodu źródłowego powyżej. Prawdopodobnie myślę o tym zupełnie niewłaściwie, ale staram się wymyślić eleganckie rozwiązanie.

 
    val lr = (l1,l2).zipped.map((t1:Int, t2:List[Int]) => 
     ... 
    )  
    println (lr) // should print List(29, 34, 39) 

Jednak nie jestem nawet pewien, czy jestem we właściwy sposób, czy powinienem to robić w sposób ciągły. Czy ktoś może pomyśleć o eleganckim rozwiązaniu mojego problemu?

+1

Może to być oczywiste dla ciebie i innych, ale może uprościć twoje myślenie, aby zdać sobie sprawę, że jest to mnożenie macierzy, w której spłaszczyłeś jedną z macierzy ('l1'.) Jeśli reprezentujesz to jako' val l1 = Lista (lista (1), lista (2)) 'i transpozycja' l2' (lub odwrotnie, w zależności od tego, jak reprezentujesz matryce) może być bardziej oczywisty. –

Odpowiedz

12

Oto jeden z możliwych sposobów, ale nie jestem pewien, czy jest to elegancki:

l2.transpose.map(sl => (l1, sl).zipped.map{ case(x,y) => x*y }.sum) 
res: List[Int] = List(29, 34, 39) 

Według @Tharabas i @ komentarzach michael_s, w końcu mamy bardziej kompaktowe rozwiązanie:

l2.transpose.map((l1,_).zipped.map(_*_).sum) 
+1

Możesz zminimalizować wewnętrzną mapę do '(_ * _)', ale poza tym, wygląda to całkiem elegancko. – Tharabas

+0

+1 Nie myślałem o "transpozycji", co daje bardzo zwięzłe rozwiązanie. – bhericher

+1

z komentarzem Tharabas, który byłby (również wyeliminowany 'sl'):' l2.transpose.map ((l1, _). Zipped.map (_ * _) .sum) ' –