복붙노트

[SCALA] 스칼라에서 어떻게 목록을 접어 중간 결과를 반환합니까?

SCALA

스칼라에서 어떻게 목록을 접어 중간 결과를 반환합니까?

나는 월의 일의 목록을 가지고있다 :

val days = List(31, 28, 31, ...)

나는 일의 누적 합계가있는 목록을 반환해야합니다

val cumDays = List(31, 59, 90)

I는 배 연산자를 사용하여 생각했습니다 :

(0 /: days)(_ + _)

I가 중간 결과의리스트를 필요로하는 반면 그러나 이것은 단지 최종 결과 (365)를 반환한다.

어쨌든 나는 우아하게 그렇게 할 수 있습니까?

해결법

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

    1.스칼라 2.8은 정확히 수행 방법 scanLeft 및 scanRight 있습니다.

    스칼라 2.8은 정확히 수행 방법 scanLeft 및 scanRight 있습니다.

    2.7의 경우이 같은 자신의 scanLeft를 정의 할 수 있습니다 :

    def scanLeft[a,b](xs:Iterable[a])(s:b)(f : (b,a) => b) =
      xs.foldLeft(List(s))( (acc,x) => f(acc(0), x) :: acc).reverse
    

    그리고 다음과 같이 사용 :

    scala> scanLeft(List(1,2,3))(0)(_+_)
    res1: List[Int] = List(0, 1, 3, 6)
    
  2. ==============================

    2.모두가 당신이 기본적으로 누적 값으로 값을 매핑 할 때, 폴딩의 어떤 종류를 사용하여 주장하는 것 같다 내가 왜 모르겠어요 ...

    모두가 당신이 기본적으로 누적 값으로 값을 매핑 할 때, 폴딩의 어떤 종류를 사용하여 주장하는 것 같다 내가 왜 모르겠어요 ...

    val daysInMonths = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
    
    val cumulated = daysInMonths.map{var s = 0; d => {s += d; s}}
    
    //--> List[Int] = List(31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
    
  3. ==============================

    3.당신은 간단하게 수행 할 수 있습니다 :

    당신은 간단하게 수행 할 수 있습니다 :

    daysInMonths.foldLeft((0, List[Int]()))
                         {(acu,i)=>(i+acu._1, i+acu._1 :: acu._2)}._2.reverse
    
  4. ==============================

    4.대신 정수의리스트로 접습니다. 스크롤의 상태로 사용할 쌍 (누적 값이 부분에서, 최종 합 누산기).

    대신 정수의리스트로 접습니다. 스크롤의 상태로 사용할 쌍 (누적 값이 부분에서, 최종 합 누산기).

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

    5.새 목록으로 목록을 접습니다. 각 반복에서, 헤드 + 다음 입력의 합인 값을 추가. 그런 다음 전체 일을 역.

    새 목록으로 목록을 접습니다. 각 반복에서, 헤드 + 다음 입력의 합인 값을 추가. 그런 다음 전체 일을 역.

    scala> val daysInMonths = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
    daysInMonths: List[Int] = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
    
    scala> daysInMonths.foldLeft(Nil: List[Int]) { (acc,next) => 
         | acc.firstOption.map(_+next).getOrElse(next) :: acc    
         | }.reverse                                             
    res1: List[Int] = List(31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
    
  6. ==============================

    6.또한 서로 연결하여 두 개의 목록이 두 번째로 첫 번째에서 마지막 값을 추가하는 동안하는 모노 이드 클래스를 만들 수 있습니다. 어떤 mutables하지없이이 참여 폴드 :

    또한 서로 연결하여 두 개의 목록이 두 번째로 첫 번째에서 마지막 값을 추가하는 동안하는 모노 이드 클래스를 만들 수 있습니다. 어떤 mutables하지없이이 참여 폴드 :

    case class CumSum(v: List[Int]) { def +(o: CumSum) = CumSum(v ::: (o.v map (_ + v.last))) }
    defined class CumSum
    
    scala> List(1,2,3,4,5,6) map {v => CumSum(List(v))} reduce (_ + _)
    res27: CumSum = CumSum(List(1, 3, 6, 10, 15, 21))
    
  7. ==============================

    7.2.7.7에서 작동 :

    2.7.7에서 작동 :

    def stepSum (sums: List [Int], steps: List [Int]) : List [Int] = steps match { 
         case Nil => sums.reverse.tail                                                  
         case x :: xs => stepSum (sums.head + x :: sums, steps.tail) }
    
    days
    res10: List[Int] = List(31, 28, 31, 30, 31)
    
    stepSum (List (0), days) 
    res11: List[Int] = List(31, 59, 90, 120, 151)
    
  8. ==============================

    8.어떠한 것도:

    어떠한 것도:

    val s:Seq[Int] = ...
    

    당신은 그 중 하나를 사용할 수 있습니다 :

    s.tail.scanLeft(s.head)(_ + _)
    s.scanLeft(0)(_ + _).tail
    

    또는 다른 답변 그러나 제안 주름이 ... Landei의 솔루션은 까다로운 것으로 인식하고 당신이 그것을 피해야한다.

    주의

    s.map { var s = 0; d => {s += d; s}} 
    //works as long `s` is strict collection
    
    val s2:Seq[Int] = s.view //still seen as Seq[Int]
    s2.map { var s = 0; d => {s += d; s}} 
    //makes really weird things! 
    //Each value'll be different whenever you'll access it!
    

    나는 Landei의 대답은 아래의 주석으로 이것에 대해 경고해야하지만 할 수 없었다 :(.

  9. from https://stackoverflow.com/questions/3224935/in-scala-how-do-i-fold-a-list-and-return-the-intermediate-results by cc-by-sa and MIT license