복붙노트

[SCALA] 어떻게 명시 적 위치에 의해서가 아니라 주어진 조건 / 상태가되지 슬라이스 가능하게하는 스칼라리스트를 확장하려면

SCALA

어떻게 명시 적 위치에 의해서가 아니라 주어진 조건 / 상태가되지 슬라이스 가능하게하는 스칼라리스트를 확장하려면

에 대한

trait Item
case class TypeA(i: Int) extends Item
case class TypeB(i: Int) extends Item

같은 항목의 스칼라 목록을 고려

val myList = List(TypeA(1), TypeB(11), TypeB(12), 
                  TypeA(2), TypeB(21), 
                  TypeA(3), TypeB(31))

목표 myList에 도포하고 인수 조건부 또는 조건을 취하는 수있는 새로운 방법의 슬라이스를 정의한다; 예를 들면

myList.slice { x => x.isInstanceOf[TypeA] }

제공 할 것이다

List(List(TypeA(1), TypeB(11), TypeB(12)), 
     List(TypeA(2), TypeB(21)), 
     List(TypeA(3), TypeB(31)))

이 예에서, 동일한 결과가 달성 될

myList.slice { case TypeA(x) => x < 10 }

많은 감사합니다.

해결법

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

    1.목록은 이미 조각 방법이있다 - 그것은 시작과 끝 인덱스 사이의 요소의 하위 집합을합니다. 당신이 찾고있는 스팬 방법의 반복되는 응용 프로그램입니다 :

    목록은 이미 조각 방법이있다 - 그것은 시작과 끝 인덱스 사이의 요소의 하위 집합을합니다. 당신이 찾고있는 스팬 방법의 반복되는 응용 프로그램입니다 :

    def span(p: (A) ⇒ Boolean): (List[A], List[A])
    

    문서화되는 :

    당신은 당신이 반복적으로 반환 된 목록 중 어느 것도 빈 없는지 확인하기 위해 역 술어이 방법과 논리의 여분의 비트를 사용하여 필요한 것을 얻을 수 있습니다.

    import annotation.tailrec
    
    def multiSpan[A](xs: List[A])(splitOn: (A) => Boolean): List[List[A]] = {
      @tailrec
      def loop(xs: List[A], acc: List[List[A]]) : List[List[A]] = xs match {
        case Nil => acc
    
        case x :: Nil => List(x) :: acc
    
        case h :: t =>
          val (pre,post) = t.span(!splitOn(_))
          loop(post, (h :: pre) :: acc)
      }
      loop(xs, Nil).reverse
    }
    

    최신 정보

    원래의 게시물에 의견 요청으로, 여기에 독립형 방법 인의 목록을 대신 풍요롭게 버전입니다 :

    implicit class AddMultispanToList[A](val list: List[A]) extends AnyVal {
      def multiSpan(splitOn: (A) => Boolean): List[List[A]] = {
        @tailrec
        def loop(xs: List[A], acc: List[List[A]]) : List[List[A]] = xs match {
          case Nil => acc
    
          case x :: Nil => List(x) :: acc
    
          case h :: t =>
            val (pre,post) = t.span(!splitOn(_))
            loop(post, (h :: pre) :: acc)
        }
        loop(list, Nil).reverse
      }
    }
    

    로 사용:

    myList.multiSpan(_.isInstanceOf[TypeA])
    
  2. ==============================

    2.왜 표준 API에서 파티션 방법을 사용하지 수 있을까?

    왜 표준 API에서 파티션 방법을 사용하지 수 있을까?

    예:

    scala> val l = List(3,5,4,6)
    l: List[Int] = List(3, 5, 4, 6)
    
    scala> 
    
    scala> val (odd,even) = l.partition(_ %2 ==1)
    odd: List[Int] = List(3, 5)
    even: List[Int] = List(4, 6)
    

    귀하의 예를 들어 :

    scala> val (typeA,typeB) = myList.partition(_.isInstanceOf[TypeA])
    typeA: List[Product with Serializable with Item] = List(TypeA(1), TypeA(2), TypeA(3))
    typeB: List[Product with Serializable with Item] = List(TypeB(11), TypeB(12), TypeB(21), TypeB(31))
    
  3. ==============================

    3.당신은 당신의 예에 대한 개조하면 되겠 어없이 (거의) 작동 필터를 찾고 있지 않습니까?

    당신은 당신의 예에 대한 개조하면 되겠 어없이 (거의) 작동 필터를 찾고 있지 않습니까?

    $ sbt console
    scala> trait Item
    scala> case class TypeA(i: Int) extends Item
    scala> case class TypeB(i: Int) extends Item
    scala> val myList = List(TypeA(1), TypeB(11), TypeB(12), 
                             TypeA(2), TypeB(21), 
                             TypeA(3), TypeB(31))
    myList: List[Product with Serializable with Item] = List(TypeA(1), TypeB(11), TypeB(12), TypeA(2), TypeB(21), TypeA(3), TypeB(31))
    

    변경되지 않은 첫 번째 작품 :

    scala> myList.filter { x => x.isInstanceOf[TypeA] }
    res0: List[Product with Serializable with Item] = List(TypeA(1), TypeA(2), TypeA(3))
    

    두 번째는 기본 케이스가 필요합니다 :

    scala> myList.filter { case TypeA(x) => x < 10; case _ => false }
    res2: List[Product with Serializable with Item] = List(TypeA(1(3))
    

    대신 부울 조건의 일부 기능을 걸립니다, 수집 항목 :

    scala> myList.collect { case z @ TypeA(x) if x < 10 => z }
    res3: List[TypeA] = List(TypeA(1), TypeA(2), TypeA(3))
    

    뿐만 아니라 변환 할 수 있습니다 :

    scala> myList.collect { case TypeA(x) if x < 10 => x }
    res4: List[Int] = List(1, 2, 3)
    
  4. from https://stackoverflow.com/questions/21800041/how-to-extend-a-scala-list-to-enable-slicing-not-by-explicit-position-but-by-giv by cc-by-sa and MIT license