Scala高次関数のmap,reduce,flatMap(フラット化),fold(折りたたみ),scan(スキャン)

39048 ワード

高次関数:
高次関数とは、パラメータとして他の関数を使用するか、結果として1つの関数を返す関数です.Scalaでは関数が「一等公民」であるため,高次関数の定義が可能である.ここでの用語は少し困惑するかもしれませんが、パラメータとして関数値を使用するか、関数値を返す「関数」と「方法」を「高次関数」と呼ぶことを約束します.最も一般的な例はScala集合クラスの高次関数mapである.
object HighOrderFunDemo02 {
     
  def main(args: Array[String]): Unit = {
     
    test2(sayOK)
  }

  //   test2        ,           ,    Unit    
  private def test2(f: () => Unit) = {
     
    f()
  }

  private def sayOK() = {
     
    println("sayOKKK...")
  }

  def sub(n1: Int): Unit = {
     }
}

/*
	   List(3,5,7)         * 2 ,                ,
	        List(6,10,14),        .
*/
val list = List(3, 5, 7, 9)
//   list.map(multiple)     
//1.   list             
//2.          multiple    =>   Int
//3.      Int ,            
//4.    multiple      3
val list2 = list.map(multiple)
println("list2=" + list2)
//List(6,10,14)
def multiple(n: Int): Int = {
     
  println("multiple    ~~")
  2 * n
}

Mapメカニズムのシミュレーション実装
object MapOperateDemo02 {
     
  def main(args: Array[String]): Unit = {
     
    /*
       List(3,5,7)         * 2 ,                ,
            List(6,10,14),        .
    */
    val list = List(3, 5, 7, 9)
    //   list.map(multiple)     
    //1.   list             
    //2.          multiple    =>   Int
    //3.      Int ,            
    //4.    multiple      3
    val list2 = list.map(multiple)
    println("list2=" + list2) //List(6,10,14)
    //     map        -    
    val myList = MyList()
    val myList2 = myList.map(multiple)
    println("myList2=" + myList2)
  }

  def multiple(n: Int): Int = {
     
    println("multiple    ~~")
    2 * n
  }
}

//     map        -    
class MyList {
     
  private val list1 = List(3, 5, 7, 9) //    
  private var list2 = List[Int]()

  //  map
  def map(f: Int => Int): List[Int] = {
     
    //    
    for (item <- this.list1) {
     
      //  ,   。。。
      list2 = list2 :+ f(item)
    }
    list2
  }
}

object MyList {
     
  def apply(): MyList = new MyList()
}

flatmapフラット化マッピング:
flatは、セット内の各要素のサブ要素を関数にマッピングし、新しいセットを返すことです.
object FlatMapDemo01 {
     
  def main(args: Array[String]): Unit = {
     
    val names = List("Alice", "Bob", "Nick")
    //     List         ,       ,        
    val names2 = names.flatMap(upper)
    println("names2=" + names2)
  }
  def upper(s: String): String = {
     
    s.toUpperCase
  }
}

フィルタセット要素のフィルタ:
基本的な説明filter:要求に合致するデータ(フィルタ)を新しい集合に配置し、val names=List(「Alice」,「Bob」,「Nick」)集合の頭文字が「A」のフィルタを新しい集合に配置する.
object FilterDemo01 {
     
  def main(args: Array[String]): Unit = {
     
    /*
           A    
    */
    val names = List("Alice", "Bob", "Nick")
    val names2 = names.filter(startA)
    println("names=" + names)
    println("names2=" + names2)
  }

  def startA(str: String): Boolean = {
     
    str.startsWith("A")
  }
}

簡略化:
reduceLeft(reduce)
object ReduceDemo01 {
     
  def main(args: Array[String]): Unit = {
     
    /*
               list     
    */
    val list = List(1, 20, 30, 4, 5)
    val res = list.reduceLeft(sum) // reduce/reduceLeft/reduceRight
    //       
    //   1 (1 + 20)
    //   2(1+20)+30
    //   3((1+20)+30)+4
    //   4(((1+20)+30)+4)+5=60
    println("res=" + res) // 60 }
    def sum(n1: Int, n2: Int): Int = {
     
      println("sum    ~~")
      n1 + n2
    }
  }
}

reduceを用いてList(3,4,2,7,5)の最小値を求める
object ReduceExercise01 {
     
  def main(args: Array[String]): Unit = {
     
    val list = List(1, 2, 3, 4, 5)

    def minus(num1: Int, num2: Int): Int = {
     
      num1 - num2
    }
    // (((1-2) - 3) - 4) - 5 = -13
    println(list.reduceLeft(minus))
    //   ? -13
    // 1 - (2 - (3 -(4 - 5))) = 3
    println(list.reduceRight(minus)) //  ? 3
    // reduce     reduceLeft
    println(list.reduce(minus))
    println("smallest=" + list.reduceLeft(min)) // 1
  }

  //      
  def min(n1: Int, n2: Int): Int = {
     
    if (n1 > n2) n2 else n1
  }
}

fold折りたたみ
  • fold関数は、リスト内のすべての要素が遍歴されるまで、前のステップで返された値を関数の最初のパラメータとして伝達し続けます.
  • はreduceLeftを簡略化版のfoldLeftと見なすことができる.
  • def reduceLeft[B >: A](@deprecatedName('f) op: (B, A) => B): B ={
         
      if (isEmpty) 
      	throw new UnsupportedOperationException("empty.reduceLeft") 
      else 
      	tail.foldLeft[B](head)(op)}
    

    reduceLeftは呼び出されたfoldLeftBであり、集合のhead要素からデフォルトで動作していることがわかります.
    object FoldDemo01 {
         
      def main(args: Array[String]): Unit = {
         
        val list = List(1, 2, 3, 4)
    
        def minus(num1: Int, num2: Int): Int = {
         
          num1 - num2
        }
        //  
        //1.                  .
        //   list.foldLeft(5)(minus)     list(5,1, 2, 3, 4) list.reduceLeft(minus)
        //   (5-1)
        //   ((5-1) - 2)
        //   (((5-1) - 2) - 3)
        //   ((((5-1)-2)-3))-4=-5
        println(list.foldLeft(5)(minus)) //       
           list.foldRight(5)(minus)     list(1, 2, 3, 4, 5) list.reduceRight(minus)
        //    (4-5)
        //    (3-(4-5))
        //    (2 -(3- (4 - 5)))
        //    1-(2-(3-(4-5)))=3
        println(list.foldRight(5)(minus)) //       
      }
    }
    

    Scanスキャン
    スキャン、すなわち、あるセットのすべての要素に対してfold操作を行いますが、生成されたすべての中間結果を1つのセットに保存します.
    object ScanDemo01 {
         
      def main(args: Array[String]): Unit = {
         
        //    
        def minus(num1: Int, num2: Int): Int = {
         
          num1 - num2
        }
    
        //5 (1,2,3,4,5) =>(5, 4, 2, -1, -5, -10)
        //Vector(5, 4, 2, -1, -5, -10)
        val i8 = (1 to 5).scanLeft(5)(minus) //IndexedSeq[Int]
        println("i8=" + i8)
    
        //    
        def add(num1: Int, num2: Int): Int = {
         
          num1 + num2
        }
    
        //(1,2,3,4,5) 5 => (20,19,17,14, 10,5)
        val i9 = (1 to 5).scanRight(5)(add) //IndexedSeq[Int]
        println("i9=" + i9)
      }
    }
    

    練習する
  • val sentence="AAAAAAAAAAAAAABBBBCCCCCDDDDDDD"sentenceの各文字をfoldLeftで1つのArrayBufferに
  • 保存する.
    import scala.collection.mutable.ArrayBuffer
    
    object Exercise02 {
         
      def main(args: Array[String]): Unit = {
         
        val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"
        val arrayBuffer = new ArrayBuffer[Char]()
        //            arrayBuffer   .
        sentence.foldLeft(arrayBuffer)(putArray)
        println("arrayBuffer=" + arrayBuffer)
      }
    
      def putArray(arr: ArrayBuffer[Char], c: Char): ArrayBuffer[Char] = {
         
        // c    arr  
        arr.append(c)
        arr
      }
    }
    
  • val sentence="AAAAAAAAAAAAAABBBBCCCCCDDDDD"マッピングセットを使用して、1つの文の中で、各アルファベットの出現回数
  • を統計する
    import scala.collection.mutable
    
    object Exercise03 {
         
      def main(args: Array[String]): Unit = {
         
        val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"
        val map2 = sentence.foldLeft(Map[Char, Int]())(charCount)
        println("map2=" + map2)
        //      map,    .
        //1.         map,           
        val map3 = mutable.Map[Char, Int]()
        sentence.foldLeft(map3)(charCount2)
        println("map3=" + map3)
      }
    
      //      map   
      def charCount(map: Map[Char, Int], char: Char): Map[Char, Int] = {
         
        map + (char -> (map.getOrElse(char, 0) + 1))
      }
    
      //     map   
      def charCount2(map: mutable.Map[Char, Int], char: Char): mutable.Map[Char, Int] = {
         
        map += (char -> (map.getOrElse(char, 0) + 1))
      }
    }