2013-06-12 9 views
5
scala> val a = List(1,2) 
a: List[Int] = List(1, 2) 

scala> val b = List(3,4) 
b: List[Int] = List(3, 4) 

scala> val c = List(5,6) 
c: List[Int] = List(5, 6) 

scala> val d = List(7,8) 
d: List[Int] = List(7, 8) 

scala> (a,b,c).zipped.toList 
res6: List[(Int, Int, Int)] = List((1,3,5), (2,4,6)) 

Teraz:Zastosowanie 4 (lub N) zbiory otrzymując tylko jedną wartość w czasie (1xn) (tj spakowany do tuple4 +)

scala> (a,b,c,d).zipped.toList 
<console>:12: error: value zipped is not a member of (List[Int], List[Int], List[Int],  List[Int]) 
       (a,b,c,d).zipped.toList 
        ^

Rozglądałem się za to gdzie indziej, w tym this one i this one, ale nie ma rozstrzygającej odpowiedzi.

Chcę wykonać następujące lub podobne:

for((itemA,itemB,itemC,itemD) <- (something)) yield itemA + itemB + itemC + itemD 

sugestie?

+1

powiązane? http://stackoverflow.com/questions/1664439/can-i-zip-more-than-two-lists-together-in-scala – WeaklyTyped

+0

ostatnia odpowiedź, combinedLists prawie daje oczekiwany wynik, jednak robi to w Odwrotna kolejność. Próbuję dowiedzieć się, jak sprawić, aby produkować prawidłowy wynik (zamiast odwracać kolejność parametrów.To również tworzy listę wartości, a nie krotkę.Dzięki! – fracca

+0

'Lista (a, b, c, d) .transpose' daje to 'List (List (1, 3, 5, 7), List (2, 4, 6, 8)). Następnie możesz użyć bezkształtnego, aby uzyskać listę krotek' List ((1, 3,5,7), (2,4,6,8)) 'Zobacz tę odpowiedź na shapeless: http://stackoverflow.com/a/11307342/390708 – Brian

Odpowiedz

2

Krótka odpowiedź:

for (List(w,x,y,z) <- List(a,b,c,d).transpose) yield (w,x,y,z) 
    // List[(Int, Int, Int, Int)] = List((1,3,5,7), (2,4,6,8)) 

Dlaczego chcesz je jako krotek, nie jestem pewien, ale nieco bardziej interesujący przypadek będzie, gdy listy są różnych typów, a na przykład chcesz połączyć je do listy obiektów:

case class Person(name: String, age: Int, height: Double, weight: Double) 
val names = List("Alf", "Betty") 
val ages = List(22, 33) 
val heights = List(111.1, 122.2) 
val weights = List(70.1, 80.2) 
val persons: List[Person] = ??? 

Rozwiązanie 1: używając transpose, jak powyżej:

for { List(name: String, age: Int, height: Double, weight: Double) <- 
     List(names, ages, heights, weights).transpose 
    } yield Person(name, age, height, weight) 

Tutaj musimy adnotacje typu w ekstraktorze list, ponieważ transpose daje List[List[Any]].

Rozwiązanie 2: używanie iteratory:

val namesIt = names.iterator 
val agesIt = ages.iterator 
val heightsIt = heights.iterator 
val weightsIt = weights.iterator 

for { name <- names } 
    yield Person(namesIt.next, agesIt.next, heightsIt.next, weightsIt.next) 

Niektórzy ludzie będą unikać iteratory ponieważ dotyczą one stan zmienny i tak nie są „funkcjonalny”.Ale są łatwe do zrozumienia, jeśli pochodzisz ze świata Java i mogą być odpowiednie, jeśli to, co masz, to już iteratory (strumienie wejściowe itp.).

+1

Podobał mi się rozwiązanie 1. Rzeczywiście mam wiele typów i muszę wygenerować klasę przypadku w moim wydatku, co pozwala mi wybrać wartości w miły sposób w sposób bezpieczny deklaratywny. – fracca

0

znaleziono możliwe rozwiązanie, choć jest to bardzo konieczne, aby mój gust:

val a = List(1,2) 
    val b = List(3,4) 
    val c = List(5,6) 
    val d = List(7,8) 

    val g : List[Tuple4[Int,Int,Int,Int]] = { 
    a.zipWithIndex.map { case (value,index) => (value, b(index), c(index), d(index))} 
    } 

zipWithIndex pozwoli mi przejść przez wszystkich innych kolekcjach. Jednak jestem pewien, że jest lepszy sposób na zrobienie tego. Jakieś sugestie?

Poprzednie próby obejmowały:

Ryan LECOMPTE na zipMany lub transpozycji.

jest to jednak lista, a nie tuple4. nie jest to tak wygodne w obsłudze, ponieważ nie mogę nazwać zmiennych.

Tranzystor jest już wbudowany w standardową bibliotekę i nie wymaga większych rodzajów importu, więc jest to preferowane, ale nie idealne.

również nieprawidłowo próbował następujący przykład bezkształtnym

scala> import Traversables._ 
import Tuples._ 
import Traversables._ 
import Tuples._ 
import scala.language.postfixOps 

scala> val a = List(1,2) 
a: List[Int] = List(1, 2) 

scala> val b = List(3,4) 
b: List[Int] = List(3, 4) 

scala> val c = List(5,6) 
c: List[Int] = List(5, 6) 

scala> val d = List(7,8) 
d: List[Int] = List(7, 8) 

scala> val x = List(a,b,c,d).toHList[Int :: Int :: Int :: Int :: HNil] map tupled 
x: Option[(Int, Int, Int, Int)] = None 
1

Shameless plug-- product-collections robi coś podobnego:

a flatZip b flatZip c flatZip d 
res0: org.catch22.collections.immutable.CollSeq4[Int,Int,Int,Int] = 
CollSeq((1,3,5,7), 
     (2,4,6,8)) 

scala> res0(0) //first row 
res1: Product4[Int,Int,Int,Int] = (1,3,5,7) 

scala> res0._1 //first column 
res2: Seq[Int] = List(1, 2)