복붙노트

[SCALA] zipWith 스칼라 (다중 서열 이상 매핑)

SCALA

zipWith 스칼라 (다중 서열 이상 매핑)

내가 가진 가정

val foo : Seq[Double] = ...
val bar : Seq[Double] = ...

나는 어디 바즈 (I) = foo는 (I) + 바 (ⅰ) 서열을 생성하고 싶습니다. 내가 생각할 수있는 한 가지 방법은이가해야 할 일

val baz : Seq[Double] = (foo.toList zip bar.toList) map ((f: Double, b : Double) => f+b)

그러나,이 추한 및 비효율적 느낌 - 나는 목록에 모두 seqs (게으른 목록과 폭발을) 변환 튜플이 임시 목록을 작성, 단지 그것을 넘어서 매핑하고 GCed 수 있도록해야합니다. 어쩌면 게으른 문제를 해결 스트림하지만, 어떤 경우에,이 Feel로 불필요하게 추한 좋아합니다. 혀짤배기에서지도 기능은 여러 개의 시퀀스를 통해지도한다. 나는 쓴다

(mapcar (lambda (f b) (+ f b)) foo bar)

그리고 더 일시적인 목록은 어디 생성되지 얻을 것입니다. 지도 - 이상 - 다중리스트는 스칼라에서 작동, 또는 정말이 작업을 수행 할 수있는 '권리'방법을 destructuring와 함께 지퍼 있습니까?

해결법

  1. ==============================

    1.당신이 원하는 기능은 zipWith라고하지만 표준 라이브러리의 일부가 아닙니다. 그것은 2.8에있을 것입니다 (UPDATE : 분명히하지, 의견을 참조).

    당신이 원하는 기능은 zipWith라고하지만 표준 라이브러리의 일부가 아닙니다. 그것은 2.8에있을 것입니다 (UPDATE : 분명히하지, 의견을 참조).

    foo zipWith((f: Double, b : Double) => f+b) bar
    

    이 Trac의 표를 참조하십시오.

  2. ==============================

    2.스칼라 2.8에서 :

    스칼라 2.8에서 :

    val baz = (foo, bar).zipped map (_ + _)
    

    그리고 같은 방법으로 두 개 이상의 피연산자에 적용됩니다. 즉 당신은이 후속 수 :

    (foo, bar, baz).zipped map (_ * _ * _)
    
  3. ==============================

    3.글쎄, 그건, 우편의 부족, 스칼라의 2.7 서열의 결핍이다. 스칼라 2.8 컬렉션은 (주들이 전혀 통일 된 디자인으로, 한 번에 생성되지 않았 음)로 온 2.7에 존재하는 임시 방법을 대체 할, 잘 생각 컬렉션 디자인을하고 있습니다.

    글쎄, 그건, 우편의 부족, 스칼라의 2.7 서열의 결핍이다. 스칼라 2.8 컬렉션은 (주들이 전혀 통일 된 디자인으로, 한 번에 생성되지 않았 음)로 온 2.7에 존재하는 임시 방법을 대체 할, 잘 생각 컬렉션 디자인을하고 있습니다.

    임시 모음을 만들지 않도록하려는 경우 지금, 당신은 스칼라 2.8에 스칼라 2.7의 "투사"또는 "보기"를 사용해야합니다. 이렇게하면 특정 지침, 특히 flatMap 및 필터, 비 엄격,지도하는 컬렉션 형식을 제공 할 것입니다. 스칼라 2.7에서 목록의 돌출부는 스트림입니다. 스칼라 2.8에서 시퀀스의 SequenceView이 있지만, 순서에 바로 거기 zipWith이, 당신도 그것을 필요로하지 않을 것이다.

    언급 한 바와 같이, JVM은 임시 개체 할당을 처리하기 위해 최적화 및 서버 모드에서 실행하는 경우, 런타임 최적화 경이로움을 수행 할 수 있다고 말했다 가졌어요. 따라서, 조기에 최적화하지 않습니다. 이 실행됩니다 조건의 코드를 테스트 - 당신은 서버 모드에서 실행 계획하지 않은 경우 코드가 실행 시간이 긴 것으로 예상되는 경우, 그을 재고하고, optmize시 / 어디서 / 필요한 경우.

    편집하다

    무엇 실제로 스칼라 2.8에서 사용할 수 것입니다 것은 이것이다 :

    (foo,bar).zipped.map(_+_)
    
  4. ==============================

    4.그것은 더 하나의 객체처럼 - 게으른 목록은 목록의 사본이 아니다. 게으른 우편 구현의 경우, 다음 항목에 대해 질문 할 때마다, 그것은 두 개의 입력 목록의 각에서 항목을 잡고 그들로부터 튜플을 생성하고, 그런 다음 패턴 매칭에와 떨어져 튜플을 깰 당신의 람다.

    그것은 더 하나의 객체처럼 - 게으른 목록은 목록의 사본이 아니다. 게으른 우편 구현의 경우, 다음 항목에 대해 질문 할 때마다, 그것은 두 개의 입력 목록의 각에서 항목을 잡고 그들로부터 튜플을 생성하고, 그런 다음 패턴 매칭에와 떨어져 튜플을 깰 당신의 람다.

    그래서 그들에 운영을 시작하기 전에 전체 입력 목록 (들)의 전체 복사본을 생성 할 필요가 절대 없습니다. 그것은 JVM에서 실행중인 모든 응용 프로그램에 매우 비슷한 할당 패턴에 귀결 - JVM이 처리하도록 최적화되어 매우 단명하지만 작은 할당, 많이.

    업데이트 : 명확하게하기 위해, 당신은 목록을 스트림 (게으른 목록)을 사용하지 않을해야합니다. 당신이 목록으로 일을 변환하지 말아야 때문에 스칼라의 스트림은 게으른 방식으로 작동 우편을합니다.

    이상적으로 알고리즘을 폭파하지 않고 두 무한 스트림 작업을 할 수 있어야한다 (이것은 물론, 어떤 폴딩을하지 않는 가정, 그러나 다만 읽고 스트림을 생성한다).

  5. ==============================

    5.업데이트 :이 "대답은"실제로 문제는 요청을 받고 처리하지 않습니다 (코멘트) 지적되고있다. 이 답변 대신 분의 요청 (M, N) 중, N은 M 원소 X를 생성 foo는 바의 각 조합을 통해 매핑한다. 그래서,이 잘못이지만, 그것의 좋은 정보부터 후대 떠났다.

    업데이트 :이 "대답은"실제로 문제는 요청을 받고 처리하지 않습니다 (코멘트) 지적되고있다. 이 답변 대신 분의 요청 (M, N) 중, N은 M 원소 X를 생성 foo는 바의 각 조합을 통해 매핑한다. 그래서,이 잘못이지만, 그것의 좋은 정보부터 후대 떠났다.

    flatMap지도와 함께이 작업을 수행하는 가장 좋은 방법입니다. 코드는 크게 말보다 말 :

    foo flatMap { f => bar map { b => f + b } }
    

    이것은 당신이 기대하는 것과 동일하게, 하나의 서열 [더블]을 생성합니다. 이 패턴은 스칼라가 실제로 어떤 구현을 일부 구문 마법을 포함 너무 일반적이다 :

    for {
      f <- foo
      b <- bar
    } yield f + b
    

    또는 대안 :

    for (f <- foo; b <- bar) yield f + b
    

    을 위해 {...} 구문은 정말이 할 수있는 가장 관용적 인 방법입니다. 필요에 따라 - 당신은 발전기 조항을 추가 (바 예를 들어, B를 <) 계속할 수 있습니다. 갑자기 당신이 이상 매핑해야하는 세 가지 Seqs이되면 따라서, 당신은 쉽게 당신의 요구 사항과 함께 당신의 구문을 확장 할 수 있습니다 (구를 화폐로 주조합니다).

  6. ==============================

    6.비슷한 작업을 직면 할 때, 나는 반복 가능 객체에 다음 포주를 추가 :

    비슷한 작업을 직면 할 때, 나는 반복 가능 객체에 다음 포주를 추가 :

    implicit class IterableOfIterablePimps[T](collOfColls: Iterable[Iterable[T]]) {
      def mapZipped[V](f: Iterable[T] => V): Iterable[V] = new Iterable[V] {
        override def iterator: Iterator[V] = new Iterator[V] {
          override def next(): V = {
            val v = f(itemsLeft.map(_.head))
            itemsLeft = itemsLeft.map(_.tail)
            v
          }
    
          override def hasNext: Boolean = itemsLeft.exists(_.nonEmpty)
    
          private var itemsLeft = collOfColls
        }
      }
    }
    

    이 데, 하나는 뭔가를 같이 할 수 있습니다 :

    val collOfColls = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
    collOfColls.mapZipped { group =>
      group // List(1, 4, 7), then List(2, 5, 8), then List(3, 6, 9)
    }
    

    꼬리와 머리가 재발 하 불려되기 때문에 신중하게 수집 유형을 고려해야주의, 중첩의 Iterable로 전달. 따라서, 이상적으로는 빠른 꼬리와 머리의 Iterable [목록] 또는 다른 모음을 통과해야한다.

    또한,이 코드는 같은 크기의 중첩 된 컬렉션을 기대하고있다. 그건 내 유스 케이스했다, 그러나 나는 필요한 경우이 향상 될 수있다 생각한다.

  7. from https://stackoverflow.com/questions/1157564/zipwith-mapping-over-multiple-seq-in-scala by cc-by-sa and MIT license