Scala에서 두 개 이상의 목록을 함께 압축 할 수 있습니까?


93

다음 스칼라 목록이 주어지면 :

val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))

어떻게 얻을 수 있습니까?

List(("a1", "a2", "a3"), ("b1", "b2", "b3"), ("c1", "c2", "c3"))

zip은 두 개의 목록을 결합하는 데만 사용할 수 있으므로 어떻게 든 기본 목록을 반복 / 축소해야한다고 생각합니다. 당연히 다음은 작동하지 않습니다.

scala> l reduceLeft ((a, b) => a zip b)
<console>:6: error: type mismatch;
 found   : List[(String, String)]
 required: List[String]
       l reduceLeft ((a, b) => a zip b)

이 작업을 수행하는 방법에 대한 제안이 있습니까? 나는 그것을하는 아주 간단한 방법을 놓치고 있다고 생각합니다.

업데이트 : 각각 M 요소가있는 N 목록 목록을 가져와 M TupleN 목록을 만들 수있는 솔루션을 찾고 있습니다.

업데이트 2 : 내 특정 사용 사례가 튜플 목록이 아닌 목록 목록을 갖는 것이 더 낫기 때문에 호박의 응답을 수락하고 있습니다. 또한 기본 방법을 사용하므로 가장 간단합니다.



확실히 주목할 가치가있는 곳 : stackoverflow.com/questions/1683312/…
Venkat Sudheer Reddy Aedama

@VenkatSudheerReddyAedama 또한 5 일 후 저도 질문했습니다. ;-)
pr1001 2015-07-22

답변:


36

나는 임의의 크기의 튜플 목록을 생성하는 것이 가능하다고 생각하지 않지만, 대신 목록 목록을 가져 오는 것에 신경 쓰지 않는다면 전치 함수 가 필요한 것을 정확하게 수행합니다.


감사합니다. 완벽하게 작동합니다! 특정 사용 사례를 살펴보면 다양한 하위 목록을 매핑하고 줄여야하므로 목록 목록이 더 좋을 것입니다.
pr1001 2009

2
@JoshCason은 "두 개 이상"이라는 가장 좁은 의미에서 확실합니다. 3 개는 실제로 2 개 이상입니다. 나는 "2 개 이상"이라는 넓은 의미로 질문을 해석했는데, 이는 임의로 많은 것을 의미합니다. 그리고이 경우 HLists 등에 도달하지 않는 한 질문이 원하는 것을 수행 할 수 없습니다 .
copumpkin

대답에있는 링크는 새로운 링크는, 고장 scala-lang.org/api/2.12.1/scala/...
라 메쉬 Maharjan

214
scala> (List(1,2,3),List(4,5,6),List(7,8,9)).zipped.toList
res0: List[(Int, Int, Int)] = List((1,4,7), (2,5,8), (3,6,9))

향후 참조를 위해.


32
이것은 세 개의 목록을 압축하는 데 유용합니다. 부끄러운 일이 세 개 이상의 목록에서 작동하지 않습니다 :(
theon

2
먼저 튜플에 있어야합니다. zipped는의 함수가 아닙니다 List.
Nathaniel Ford

6
zippedScala 2.13에서는 더 이상 사용되지 않습니다. 2.13에 수행l1.lazyZip(l2).lazyZip(l3).toList
세스 Tisue

30

따라서이 코드는 OP의 요구에 응답하지 않습니다. 이것은 4 년 된 스레드이기 때문일뿐만 아니라 제목 질문에 대한 답변을 제공하므로 누군가 유용하다고 생각할 수도 있습니다.

3 개의 컬렉션을 압축하려면 :

as zip bs zip cs map { 
  case ((a,b), c) => (a,b,c)
}

4 컬렉션을 수행하는 방법은 다음과 같습니다.as zip bs zip cs zip ds map { case ((a,b),c)} map {case ((a,b),c,d)=>(a,b,c,d)}
James Tobin

1
@JamesTobin, u 단축as zip bs zip cs zip ds map {case (((a,b),c),d)=>(a,b,c,d) }
keepscoding

다양한 유형의 목록에 적합합니다.
FP Freely

11

예, zip3 사용 .


2
감사합니다.하지만 3 개의 목록에서만 작동합니다. 각각 M 요소가있는 N 목록 목록을 가져와 M TupleN 목록을 만들 수있는 솔루션을 찾고 있습니다.
pr1001 2009

6

transpose트릭을 수행합니다. 가능한 알고리즘은 다음과 같습니다.

def combineLists[A](ss:List[A]*) = {
    val sa = ss.reverse;
    (sa.head.map(List(_)) /: sa.tail)(_.zip(_).map(p=>p._2 :: p._1))
}

예를 들면 :

combineLists(List(1, 2, 3), List(10,20), List(100, 200, 300))
// => List[List[Int]] = List(List(1, 10, 100), List(2, 20, 200))

대답은 입력에서 가장 짧은 목록의 크기로 잘립니다.

combineLists(List(1, 2, 3), List(10,20))
// => List[List[Int]] = List(List(1, 10), List(2, 20))

1
이 대답은 거의 트릭을 수행하지만 요소를 뒤집습니다. 예상 된 순서로 출력을 생성하는 개선 된 버전을 제안 할 수 있습니까? 감사합니다
fracca

순서를 유지 수정 된 버전 : def combineLists[A](ss:List[A]*) = { val sa = ss.reverse; (sa.head.map(List(_)) /: sa.tail)(_.zip(_).map(p=>p._2 :: p._1)) }
rogermenezes

5

모든 다른 클래스 등의 다른 튜플 크기의 스칼라 취급은 ( Tuple1, Tuple2, Tuple3, Tuple4, ..., Tuple22그들은에서 모든 상속을 할 때) Product, 특성 실제로 튜플의 다른 크기의 데이터 값을 사용하려면 특성은 충분한 정보를 전달하지 않습니다 모두 같은 함수에 의해 반환 될 수 있다면. (그리고 스칼라의 제네릭은이 경우를 처리 할만큼 강력하지 않습니다.)

가장 좋은 방법은 22 개의 모든 튜플 크기에 대해 zip 함수의 오버로드를 작성하는 것입니다. 코드 생성기가 도움이 될 것입니다.


5

적용 가능한 scalaz / cats / (여기에 좋아하는 기능적 라이브러리를 삽입하십시오) 경로를 따르고 싶지 않다면, (_, _)구문이 중첩에 약간 어색 하긴하지만 패턴 매칭을 사용하는 것이 좋습니다. 변경해 보겠습니다.

import scala.{Tuple2 => &}

for (i1 & i2 & i3 & i4 <- list1 zip list2 zip list3 zip list4) yield (i1, i2, i3, i4)

&여기에 임의의 선택을해야 좋은 중위 보이는 것도있다. 하지만 코드 검토 중에 몇 가지 눈썹을 올릴 수 있습니다.

또한 어떤 작업을해야 할 수 있습니다 zip(예를 Future들)


5

나는 그것이 반복적이지 않고 가능하다고 믿지 않는다. 한 가지 간단한 이유는 요청하는 함수의 반환 유형을 정의 할 수 없다는 것입니다.

예를 들어 입력이 List(List(1,2), List(3,4))이면 반환 유형은 List[Tuple2[Int]]. 세 개의 요소가있는 경우 반환 유형은 List[Tuple3[Int]]입니다.

List[AnyRef], 또는를 반환 List[Product]한 다음 각 조건에 대해 하나씩 여러 케이스를 만들 수 있습니다.

일반 목록 전치의 경우 다음과 같이 작동합니다.

def transpose[T](l: List[List[T]]): List[List[T]] = l match {
  case Nil => Nil
  case Nil :: _ => Nil
  case _ => (l map (_.head)) :: transpose(l map (_.tail))
}

임의 크기의 목록에는 작동하지 않습니다. 예 : transpose (List (List ( "a", "b"), List ( "c")))
Venkat Sudheer Reddy Aedama

1
@VenkatSudheerReddyAedama 불완전한 행렬의 전치가 나에게 의미가 없습니다. 경우, 귀하의 예를 촬영하려면 c에 부합 a나에 b? 그리고 그것이 다른 것과 일치한다는 것을 어떻게 표현 하시겠습니까?
Daniel C. Sobral 2015 년

동의합니다. 그것은 불완전한 행렬입니다. 나는 zipAll의 라인을 따라 무언가를 찾고 있었다. 제 경우에는 다음 ca일치합니까 (즉, 인덱스와 인라인)?
Venkat Sudheer Reddy Aedama

2

product-collections 에는 flatZip최대 22 개의 작업이 있습니다.

scala> List(1,2,3) flatZip Seq("a","b","c") flatZip Vector(1.0,2.0,3.0) flatZip Seq(9,8,7)
res1: com.github.marklister.collections.immutable.CollSeq4[Int,String,Double,Int] = 
CollSeq((1,a,1.0,9),
        (2,b,2.0,8),
        (3,c,3.0,7))

0

Scalaz 사용 :

import scalaz.Zip
import scalaz.std.list._

// Zip 3
Zip[List].ap.tuple3(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"))

// Zip 4
Zip[List].ap.tuple4(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"),
                    List("a4", "b4"))

// Zip 5
Zip[List].ap.tuple5(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"),
                    List("a4", "b4"),
                    List("a5", "b5"))

5 이상 :

// Zip 6
Zip[List].ap.apply6(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"),
                    List("a4", "b4"),
                    List("a5", "b5"),
                    List("a6", "b6"))((_, _, _, _, _, _))

// Zip 7
Zip[List].ap.apply7(List("a1", "b1"),
                    List("a2", "b2"),
                    List("a3", "b3"),
                    List("a4", "b4"),
                    List("a5", "b5"),
                    List("a6", "b6"),
                    List("a7", "b7"))((_, _, _, _, _, _, _))

...

// Zip 12
Zip[List].ap.apply12(List("a1", "b1"),
                     List("a2", "b2"),
                     List("a3", "b3"),
                     List("a4", "b4"),
                     List("a5", "b5"),
                     List("a6", "b6"),
                     List("a7", "b7"),
                     List("a8", "b8"),
                     List("a9", "b9"),
                     List("a10", "b10"),
                     List("a11", "b11"),
                     List("a12", "b12"))((_, _, _, _, _, _, _, _, _, _, _, _))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.