복붙노트

[SCALA] 목록의 하나에 Eithers의 목록을 설정하는 가장 좋은 방법은?

SCALA

목록의 하나에 Eithers의 목록을 설정하는 가장 좋은 방법은?

어떤 좌파가 목록에있을 경우, 나는 반환, 나는 아래, 나는 Eithers의 목록을 어디에서 같은 몇 가지 코드를 가지고 있고, 나는 (이 경우) 특히 ... 목록의 하나로 돌려하려면 그 목록의 왼쪽, 그렇지 않으면 나는 권리의 목록의 오른쪽을 반환합니다.

val maybe: List[Either[String, Int]] = getMaybe
val (strings, ints) = maybe.partition(_.isLeft)
strings.map(_.left.get) match {
  case Nil => Right(ints.map(_.right.get))
  case stringList => Left(stringList)
}

GET을 호출하면 항상 내가 뭔가를 놓친해야처럼 느끼게한다.

이 작업을 수행 할 수있는 더 관용적 방법이 있나요?

해결법

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

    1.

    data.partition(_.isLeft) match {                            
      case (Nil,  ints) => Right(for(Right(i) <- ints) yield i)        
      case (strings, _) => Left(for(Left(s) <- strings) yield s)
    }
    

    한 패스의 경우 :

    data.partition(_.isLeft) match {                            
      case (Nil,  ints) => Right(for(Right(i) <- ints.view) yield i)        
      case (strings, _) => Left(for(Left(s) <- strings.view) yield s)
    }
    
  2. ==============================

    2.스칼라 책 기능적 프로그래밍에서 솔루션.

    스칼라 책 기능적 프로그래밍에서 솔루션.

    def sequence[E,A](es: List[Either[E,A]]): Either[E,List[A]] = 
        traverse(es)(x => x)
    
    def traverse[E,A,B](es: List[A])(f: A => Either[E, B]): Either[E, List[B]] = 
        es match {
          case Nil => Right(Nil)
          case h::t => (f(h) map2 traverse(t)(f))(_ :: _)
        }
    def map2[EE >: E, B, C](a: Either[E, A], b: Either[EE, B])(f: (A, B) => C): 
       Either[EE, C] = for { a1 <- a; b1 <- b } yield f(a1,b1)
    
  3. ==============================

    3.

    val list = List(Left("x"),Right(2), Right(4))
    val strings = for (Left(x) <- list) yield(x)
    val result = if (strings.isEmpty) Right(for (Right(x) <- list) yield(x)) 
                 else Left(strings)
    
  4. ==============================

    4.스칼라 2.13부터, 대부분의 컬렉션은 이제 파티션 요소가있는 반환 중 하나를 오른쪽 또는 왼쪽 함수를 기반으로 partitionMap 방법으로 제공됩니다.

    스칼라 2.13부터, 대부분의 컬렉션은 이제 파티션 요소가있는 반환 중 하나를 오른쪽 또는 왼쪽 함수를 기반으로 partitionMap 방법으로 제공됩니다.

    우리의 경우, 우리는 심지어 우리가 이미 권리와 좌파가 있기 때문에 파티션을 정의하기 위해 오른쪽 또는 왼쪽에 우리의 입력을 변환하는 기능이 필요하지 않습니다. 정체성 따라서 간단한 사용!

    그런 다음 왼쪽, 오른쪽이 있는지 여부에 따라 왼쪽, 오른쪽과 권리의 결과로 분할 된 튜플 일치하는 간단한 문제입니다 :

    eithers.partitionMap(identity) match {
      case (Nil, rights) => Right(rights)
      case (lefts, _)    => Left(lefts)
    }
    // * List[Either[String, Int]] = List(Right(3), Left("error x"), Right(7))
    //         => Either[List[String],List[Int]] = Left(List(error x))
    // * List[Either[String, Int]] = List(Right(3), Right(7))
    //         => Either[List[String],List[Int]] = Right(List(3, 7))
    

    partitionMap의 이해를 위해 여기에 중간 단계의 결과는 다음과 같습니다

    List(Right(3), Left("error x"), Right(7)).partitionMap(identity)
    // (List[String], List[Int]) = (List(error x), List(3, 7))
    
  5. ==============================

    5.다음과 같이 분할의 일반화 된 버전을 작성할 수 있습니다 :

    다음과 같이 분할의 일반화 된 버전을 작성할 수 있습니다 :

    def split[X, CC[X] <: Traversable[X], A, B](l : CC[Either[A, B]])
       (implicit bfa : CanBuildFrom[Nothing, A, CC[A]], bfb : CanBuildFrom[Nothing, B, CC[B]]) : (CC[A], CC[B]) = {
      def as = {
        val bf = bfa()
        bf ++= (l collect { case Left(x) => x})
        bf.result
      }
    
      def bs = {
        val bf = bfb()
        bf ++= (l collect { case Right(x) => x})
        bf.result
      }
    
      (as, bs)
    }
    

    이러한 것을 :

    scala> List(Left("x"),Right(2), Right(4)) : List[Either[java.lang.String,Int]]
    res11: List[Either[java.lang.String,Int]] = List(Left(x), Right(2), Right(4))
    
    scala> split(res11)
    res12: (List[java.lang.String], List[Int]) = (List(x),List(2, 4))
    
    scala> Set(Left("x"),Right(2), Right(4)) : Set[Either[java.lang.String,Int]]
    res13: Set[Either[java.lang.String,Int]] = Set(Left(x), Right(2), Right(4))
    
    scala> split(res13)
    res14: (Set[java.lang.String], Set[Int]) = (Set(x),Set(2, 4))
    
  6. ==============================

    6.나는 종류는 크리스의 대답과 빅토르의 여기에서의 병합입니다 ..하지만 여기에 대안의 이에 대한 모든 업보를하지 않으려의 :

    나는 종류는 크리스의 대답과 빅토르의 여기에서의 병합입니다 ..하지만 여기에 대안의 이에 대한 모든 업보를하지 않으려의 :

    def split[CC[X] <: Traversable[X], A, B](xs: CC[Either[A, B]])
       (implicit bfa: CanBuildFrom[Nothing, A, CC[A]], bfb: CanBuildFrom[Nothing, B, CC[B]]) : (CC[A], CC[B]) =
      xs.foldLeft((bfa(), bfb())) {
        case ((as, bs), l@Left(a)) => (as += a, bs)
        case ((as, bs), r@Right(b)) => (as, bs += b)
      } match {
        case (as, bs) => (as.result(), bs.result())
      }
    

    예:

    scala> val eithers: List[Either[String, Int]] = List(Left("Hi"), Right(1))
    eithers: List[Either[String,Int]] = List(Left(Hi), Right(1))
    
    scala> split(eithers)
    res0: (List[String], List[Int]) = (List(Hi),List(1))
    
  7. ==============================

    7.좀 더 일반적이고 또한 기능적인 무언가가 다음 고양이 라이브러리에서 검증 된 가지고 싶다면 당신이 원하는 수있는 유형입니다. 이 오류를 집계 할 수 있습니다 같은 것입니다. 그리고 NonEmptyList와 함께 정말 강력 할 수있다.

    좀 더 일반적이고 또한 기능적인 무언가가 다음 고양이 라이브러리에서 검증 된 가지고 싶다면 당신이 원하는 수있는 유형입니다. 이 오류를 집계 할 수 있습니다 같은 것입니다. 그리고 NonEmptyList와 함께 정말 강력 할 수있다.

    http://typelevel.org/cats/datatypes/validated.html

  8. from https://stackoverflow.com/questions/6489584/best-way-to-turn-a-lists-of-eithers-into-an-either-of-lists by cc-by-sa and MIT license