복붙노트

[SCALA] 어떻게 줄이기 위해 서열 [어느 [A, B]] 어느 [A, 서열 [B]에?

SCALA

어떻게 줄이기 위해 서열 [어느 [A, B]] 어느 [A, 서열 [B]에?

왼쪽 에러 메시지로 되 eithers의 서열 SEQ [어느 [문자열 A]] 주어진. 내가 어느 가져올 [문자열, 서열를 [A] 나는 오른쪽 얻을 경우 (A 서열 될 것입니다 [A]) 시퀀스의 모든 요소가 오른쪽 경우. 적어도 하나의 왼쪽 (오류 메시지)가있는 경우에, 나는 첫 번째 오류 메시지 또는 모든 오류 메시지의 연결을 취득하고 싶습니다.

물론 당신은 scalaz 코드를 게시 할 수 있지만이 또한 그것을 사용하지 않는 코드에 관심이 있어요.

나는 원래 메시지의 어느 [서열 [A], 서열은 [B]를] 반영하기 위해 몸을 요청 제목을 변경했습니다.

해결법

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

    1.편집 : 나는 당신의 질문의 제목 중 하나 [] 서열 [A], 서열 [B]를 요청 놓친, 그러나 나는 "나는 첫 번째 오류 메시지 또는 모든 오류 메시지의 연결을 취득하고 싶습니다"읽기 않았고, 이것은 당신에게 전자를 줄 것이다 :

    편집 : 나는 당신의 질문의 제목 중 하나 [] 서열 [A], 서열 [B]를 요청 놓친, 그러나 나는 "나는 첫 번째 오류 메시지 또는 모든 오류 메시지의 연결을 취득하고 싶습니다"읽기 않았고, 이것은 당신에게 전자를 줄 것이다 :

    def sequence[A, B](s: Seq[Either[A, B]]): Either[A, Seq[B]] =
      s.foldRight(Right(Nil): Either[A, List[B]]) {
        (e, acc) => for (xs <- acc.right; x <- e.right) yield x :: xs
      }
    
    scala> sequence(List(Right(1), Right(2), Right(3)))
    res2: Either[Nothing,Seq[Int]] = Right(List(1, 2, 3))
    
    scala> sequence(List(Right(1), Left("error"), Right(3)))
    res3: Either[java.lang.String,Seq[Int]] = Left(error)
    

    Scalaz 사용 :

    val xs: List[Either[String, Int]] = List(Right(1), Right(2), Right(3))
    
    scala> xs.sequenceU
    res0:  scala.util.Either[String,List[Int]] = Right(List(1, 2, 3))
    
  2. ==============================

    2.여기에 내 걸릴이야, 시작 시퀀스 XS를 감안할 때 :

    여기에 내 걸릴이야, 시작 시퀀스 XS를 감안할 때 :

    xs collectFirst { case x@Left(_) => x } getOrElse
      Right(xs collect {case Right(x) => x})
    

    양자 택일 [A] 문자열 서열 ​​[]로 첫 번째 오차를 구하는 문제 본문에 대답이 존재. 그것은 분명 제목에 질문에 대한 올바른 답이 아니다

    모든 오류를 반환합니다 :

    val lefts = xs collect {case Left(x) => x }
    def rights = xs collect {case Right(x) => x}
    if(lefts.isEmpty) Right(rights) else Left(lefts)
    

    이 단지 필요에 따라 평가 될 것이다, 그래서 필요한 경우 권리,하는 방법으로 정의되어 있습니다

  3. ==============================

    3.여기에 scalaz 코드는 다음과 같습니다

    여기에 scalaz 코드는 다음과 같습니다

    _.순서

  4. ==============================

    4.그것은 작동합니다 :

    그것은 작동합니다 :

    def unfoldRes[A](x: Seq[Either[String, A]]) = x partition {_.isLeft} match {
      case (Seq(), r) => Right(r map {_.right.get})
      case (l, _) => Left(l map {_.left.get} mkString "\n")
    }
    

    당신은 왼쪽에 결과를 분할하고 왼쪽이 비어있는 경우 오른쪽, 그렇지 않으면 마우스 오른쪽 버튼을 구축 왼쪽을 구축 할 수 있습니다.

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

    5.케빈의 솔루션을 구축하고, 하스켈의 어느 유형에서 비트를 훔쳐, 그렇게 같은 방법 partitionEithers를 만들 수 있습니다 :

    케빈의 솔루션을 구축하고, 하스켈의 어느 유형에서 비트를 훔쳐, 그렇게 같은 방법 partitionEithers를 만들 수 있습니다 :

    def partitionEithers[A, B](es: Seq[Either[A, B]]): (Seq[A], Seq[B]) =
      es.foldRight (Seq.empty[A], Seq.empty[B]) { case (e, (as, bs)) =>
        e.fold (a => (a +: as, bs), b => (as, b +: bs))
      }
    

    그리고 당신의 솔루션을 구축하는 것을 사용

    def unroll[A, B](es: Seq[Either[A, B]]): Either[Seq[A], Seq[B]] = {
      val (as, bs) = partitionEithers(es)
      if (!as.isEmpty) Left(as) else Right(bs)
    }
    
  6. ==============================

    6.스칼라 2.13부터, 대부분의 컬렉션은 파티션 요소가 오른쪽 또는 왼쪽 중 하나에 항목을 매핑하는 기능을 기반으로 partitionMap 방법으로 제공됩니다.

    스칼라 2.13부터, 대부분의 컬렉션은 파티션 요소가 오른쪽 또는 왼쪽 중 하나에 항목을 매핑하는 기능을 기반으로 partitionMap 방법으로 제공됩니다.

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

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

    eithers.partitionMap(identity) match {
      case (Nil, rights)       => Right(rights)
      case (firstLeft :: _, _) => Left(firstLeft)
    }
    
    // * val eithers: List[Either[String, Int]] = List(Right(1), Right(2), Right(3))
    //         => Either[String,List[Int]] = Right(List(1, 2, 3))
    // * val eithers: List[Either[String, Int]] = List(Right(1), Left("error1"), Right(3), Left("error2"))
    //         => Either[String,List[Int]] = Left("error1")
    

    중간 단계의 세부 사항 (partitionMap) :

    List(Right(1), Left("error1"), Right(3), Left("error2")).partitionMap(identity)
    // => (List[String], List[Int]) = (List("error1", "error2"), List(1, 3))
    
  7. ==============================

    7.여기에 나의 접근 방식이다 - 나는 어느 쪽을 사용하는 데 사용하고 있지 않다 어쩌면 더 우아한 해결책이 있습니다 :

    여기에 나의 접근 방식이다 - 나는 어느 쪽을 사용하는 데 사용하고 있지 않다 어쩌면 더 우아한 해결책이 있습니다 :

    def condense [A] (sesa: Seq [Either [String, A]]): Either [String, Seq [A]] = {
      val l = sesa.find (e => e.isLeft)
      if (l == None) Right (sesa.map (e => e.right.get)) 
      else Left (l.get.left.get)
    }
    
    condense (List (Right (3), Right (4), Left ("missing"), Right (2)))
    // Either[String,Seq[Int]] = Left(missing)
    condense (List (Right (3), Right (4), Right (1), Right (2)))
    // Either[String,Seq[Int]] = Right(List(3, 4, 1, 2))
    

    좌 (l.get.left.get)이 재미 조금 보이지만, L 자체가 아닌 하나 [A 서열 [B], 및 필요에 재배치 어느 [A, B]이다.

  8. ==============================

    8.내 대답은 @Garrett 로우의 유사합니다 그러나 foldLeft을 사용하지 않고 서열에 추가하는 것보다 서열에 (또한 참조 왜 foldRight 및 reduceRight이 꼬리 재귀되지 않습니다?)과의 앞에 추가합니다 (참조 : 왜 목록 나쁜에 추가됩니다).

    내 대답은 @Garrett 로우의 유사합니다 그러나 foldLeft을 사용하지 않고 서열에 추가하는 것보다 서열에 (또한 참조 왜 foldRight 및 reduceRight이 꼬리 재귀되지 않습니다?)과의 앞에 추가합니다 (참조 : 왜 목록 나쁜에 추가됩니다).

    scala> :paste
    // Entering paste mode (ctrl-D to finish)
    
    def partitionEitherSeq[A,B](eitherSeq: Seq[Either[A,B]]): (Seq[A], Seq[B]) =
      eitherSeq.foldLeft(Seq.empty[A], Seq.empty[B]) { (acc, next) =>
      val (lefts, rights) = acc
      next.fold(error => (lefts :+ error, rights), result => (lefts, rights :+ result))
    }
    
    // Exiting paste mode, now interpreting.
    
    partitionEitherSeq: [A, B](eitherSeq: Seq[Either[A,B]])(Seq[A], Seq[B])
    
    scala> partitionEitherSeq(Seq(Right("Result1"), Left("Error1"), Right("Result2"), Right("Result3"), Left("Error2")))
    res0: (Seq[java.lang.String], Seq[java.lang.String]) = (List(Error1, Error2),List(Result1, Result2, Result3))
    
  9. from https://stackoverflow.com/questions/7230999/how-to-reduce-seqeithera-b-to-eithera-seqb by cc-by-sa and MIT license