복붙노트

[SCALA] (왼쪽 / 오른쪽) 배, 줄이거 나 스캔?

SCALA

(왼쪽 / 오른쪽) 배, 줄이거 나 스캔?

언제 reduceLeft, reduceRight, foldLeft, foldRight, scanLeft 또는 scanRight을 사용해야합니까?

나는 그들의 차이의 직관 / 개요를 원하는 - 아마도 몇 가지 간단한 예제와 함께.

해결법

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

    1.일반적으로, 모든 6 개 배 기능 집합의 각 요소에 이진 연산자를 적용한다. 각 단계의 결과는 (이진 연산자의 두 개의 인자들 중 하나에 대한 입력으로) 다음 단계로 전달된다. 이 방법으로 우리는 결과를 쌓아 수 있습니다.

    일반적으로, 모든 6 개 배 기능 집합의 각 요소에 이진 연산자를 적용한다. 각 단계의 결과는 (이진 연산자의 두 개의 인자들 중 하나에 대한 입력으로) 다음 단계로 전달된다. 이 방법으로 우리는 결과를 쌓아 수 있습니다.

    reduceLeft 및 reduceRight은 하나의 결과를 쌓아.

    foldLeft 및 foldRight은 시작 값을 사용하는 하나의 결과를 쌓아.

    scanLeft 및 scanRight은 시작 값을 사용하여 중간 누적 결과 집합을 쌓아.

    왼쪽 및 전달에서 ...

    ABC 요소의 컬렉션 이진 연산자 우리가 다른 스크롤 기능이 무엇 탐험 추가 (C A에서) 수집 좌측 요소로부터 전방으로 이동할 때 :

    val abc = List("A", "B", "C")
    
    def add(res: String, x: String) = { 
      println(s"op: $res + $x = ${res + x}")
      res + x
    }
    
    abc.reduceLeft(add)
    // op: A + B = AB
    // op: AB + C = ABC    // accumulates value AB in *first* operator arg `res`
    // res: String = ABC
    
    abc.foldLeft("z")(add) // with start value "z"
    // op: z + A = zA      // initial extra operation
    // op: zA + B = zAB
    // op: zAB + C = zABC
    // res: String = zABC
    
    abc.scanLeft("z")(add)
    // op: z + A = zA      // same operations as foldLeft above...
    // op: zA + B = zAB
    // op: zAB + C = zABC
    // res: List[String] = List(z, zA, zAB, zABC) // maps intermediate results
    

    오른쪽에서 뒤로 ...

    우리가 RIGHT 요소로 시작하고 우리의 바이너리 연산자는 결과를 축적에 우리가 지금 두 번째 인수를 알 수 있습니다 (A와 C에서) 뒤로 가면 (운영자가 동일, 우리는 단지 자신의 역할을 명확하게하기 위해 인수 이름을 전환 ) :

    def add(x: String, res: String) = {
      println(s"op: $x + $res = ${x + res}")
      x + res
    }
    
    abc.reduceRight(add)
    // op: B + C = BC
    // op: A + BC = ABC  // accumulates value BC in *second* operator arg `res`
    // res: String = ABC
    
    abc.foldRight("z")(add)
    // op: C + z = Cz
    // op: B + Cz = BCz
    // op: A + BCz = ABCz
    // res: String = ABCz
    
    abc.scanRight("z")(add)
    // op: C + z = Cz
    // op: B + Cz = BCz
    // op: A + BCz = ABCz
    // res: List[String] = List(ABCz, BCz, Cz, z)
    

    .

    왼쪽 및 전달에서 ...

    대신하면 우리는 우리가 우리의 이항 연산자 마이너스의 첫 번째 인수의 고해상도를 통해 결과를 쌓아 올린 것 모음의 왼쪽 요소부터 감산에 의해 어떤 결과를 해제 쌓아했다 :

    val xs = List(1, 2, 3, 4)
    
    def minus(res: Int, x: Int) = {
      println(s"op: $res - $x = ${res - x}")
      res - x
    }
    
    xs.reduceLeft(minus)
    // op: 1 - 2 = -1
    // op: -1 - 3 = -4  // de-cumulates value -1 in *first* operator arg `res`
    // op: -4 - 4 = -8
    // res: Int = -8
    
    xs.foldLeft(0)(minus)
    // op: 0 - 1 = -1
    // op: -1 - 2 = -3
    // op: -3 - 3 = -6
    // op: -6 - 4 = -10
    // res: Int = -10
    
    xs.scanLeft(0)(minus)
    // op: 0 - 1 = -1
    // op: -1 - 2 = -3
    // op: -3 - 3 = -6
    // op: -6 - 4 = -10
    // res: List[Int] = List(0, -1, -3, -6, -10)
    

    오른쪽에서 뒤로 ...

    하지만 지금은 xRight 변화를 조심해! xRight 변동의 (축소) 누적 값이 우리의 이진 연산자 마이너스의 제 파라미터 입술에 전달되어 기억

    def minus(x: Int, res: Int) = {
      println(s"op: $x - $res = ${x - res}")
      x - res
    }
    
    xs.reduceRight(minus)
    // op: 3 - 4 = -1
    // op: 2 - -1 = 3  // de-cumulates value -1 in *second* operator arg `res`
    // op: 1 - 3 = -2
    // res: Int = -2
    
    xs.foldRight(0)(minus)
    // op: 4 - 0 = 4
    // op: 3 - 4 = -1
    // op: 2 - -1 = 3
    // op: 1 - 3 = -2
    // res: Int = -2
    
    xs.scanRight(0)(minus)
    // op: 4 - 0 = 4
    // op: 3 - 4 = -1
    // op: 2 - -1 = 3
    // op: 1 - 3 = -2
    // res: List[Int] = List(-2, 3, -1, 4, 0) 
    

    마지막 목록 (-2, 3, -1, 4, 0) 아마 당신은 직관적으로 기대하는 것입니다!

    보시다시피, 당신은 당신의 foldX 단순히 대신 scanX을 실행하고 각 단계에서의 누적 결과를 디버깅에 의해 무엇을하고 있는지 확인할 수 있습니다.

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

    2.일반적으로 왼쪽에있는 데이터를 축적하여 FOLD, SCAN 방법은 작동 줄이고 RIGHT 변수를 변경 계속. 그들 사이의 가장 큰 차이점은 FOLD가 감소입니다 : -

    일반적으로 왼쪽에있는 데이터를 축적하여 FOLD, SCAN 방법은 작동 줄이고 RIGHT 변수를 변경 계속. 그들 사이의 가장 큰 차이점은 FOLD가 감소입니다 : -

    항상 즉, 사용자 정의 시작 값 시드 값으로 시작됩니다 접습니다. 배는 시드 값을 돌려주기 때문에 어디 모음이 비어있는 경우 예외가 발생합니다 줄일 수 있습니다. 항상 단일 값을 발생합니다.

    스캔이 좌측 또는 우측의 항목 중 일부의 처리 순서에 사용되는, 우리는 후속 계산에서 이전의 결과를 사용할 수있다. 그게 우리가 항목을 스캔 할 수 있음을 의미합니다. 항상 컬렉션을 발생합니다.

    아래에 언급 된 코드에 대한 출력의 일부는 다음과 같습니다 -

    번호 목록 스캐닝 동작을 이용하여 (-1,0,1,2, -2) 목록 (시드 값 0을 사용)

    감소 문자열리스트의리스트를 조작하여 배 ( "A", "B", "C", "D", "E")

    코드 :

    object ScanFoldReduce extends App {
    
        val list = List("A","B","C","D","E")
                println("reduce (a+b) "+list.reduce((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  ")
                    a+b
                }))
    
                println("reduceLeft (a+b) "+list.reduceLeft((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  ")
                    a+b
                }))
    
                println("reduceLeft (b+a) "+list.reduceLeft((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (b+a)+"  " )
                    b+a
                }))
    
                println("reduceRight (a+b) "+list.reduceRight((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  " )
                    a+b
                }))
    
                println("reduceRight (b+a) "+list.reduceRight((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (b+a)+"  ")
                    b+a
                }))
    
                println("scan            "+list.scan("[")((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  " )
                    a+b
                }))
                println("scanLeft (a+b)  "+list.scanLeft("[")((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  " )
                    a+b
                }))
                println("scanLeft (b+a)  "+list.scanLeft("[")((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (b+a)+"  " )
                    b+a
                }))
                println("scanRight (a+b) "+list.scanRight("[")((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  " )
                    a+b
                }))
                println("scanRight (b+a) "+list.scanRight("[")((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (b+a)+"  " )
                    b+a
                }))
    //Using numbers
         val list1 = List(-2,-1,0,1,2)
    
                println("reduce (a+b) "+list1.reduce((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  ")
                    a+b
                }))
    
                println("reduceLeft (a+b) "+list1.reduceLeft((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  ")
                    a+b
                }))
    
                println("reduceLeft (b+a) "+list1.reduceLeft((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (b+a)+"  " )
                    b+a
                }))
    
                println("      reduceRight (a+b) "+list1.reduceRight((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  " )
                    a+b
                }))
    
                println("      reduceRight (b+a) "+list1.reduceRight((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (b+a)+"  ")
                    b+a
                }))
    
                println("scan            "+list1.scan(0)((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  " )
                    a+b
                }))
    
                println("scanLeft (a+b)  "+list1.scanLeft(0)((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  " )
                    a+b
                }))
    
                println("scanLeft (b+a)  "+list1.scanLeft(0)((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (b+a)+"  " )
                    b+a
                }))
    
                println("scanRight (a+b)         "+list1.scanRight(0)((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  " )
                    a+b}))
    
                println("scanRight (b+a)         "+list1.scanRight(0)((a,b)=>{
                    print("{"+a+","+b+"}=>"+ (a+b)+"  " )
                    b+a}))
    }
    
  3. from https://stackoverflow.com/questions/17408880/reduce-fold-or-scan-left-right by cc-by-sa and MIT license