Scala高次関数のmap,reduce,flatMap(フラット化),fold(折りたたみ),scan(スキャン)
高次関数:
高次関数とは、パラメータとして他の関数を使用するか、結果として1つの関数を返す関数です.Scalaでは関数が「一等公民」であるため,高次関数の定義が可能である.ここでの用語は少し困惑するかもしれませんが、パラメータとして関数値を使用するか、関数値を返す「関数」と「方法」を「高次関数」と呼ぶことを約束します.最も一般的な例はScala集合クラスの高次関数mapである.
Mapメカニズムのシミュレーション実装
flatmapフラット化マッピング:
flatは、セット内の各要素のサブ要素を関数にマッピングし、新しいセットを返すことです.
フィルタセット要素のフィルタ:
基本的な説明filter:要求に合致するデータ(フィルタ)を新しい集合に配置し、val names=List(「Alice」,「Bob」,「Nick」)集合の頭文字が「A」のフィルタを新しい集合に配置する.
簡略化:
reduceLeft(reduce)
reduceを用いてList(3,4,2,7,5)の最小値を求める
fold折りたたみ fold関数は、リスト内のすべての要素が遍歴されるまで、前のステップで返された値を関数の最初のパラメータとして伝達し続けます. はreduceLeftを簡略化版のfoldLeftと見なすことができる.
reduceLeftは呼び出されたfoldLeftBであり、集合のhead要素からデフォルトで動作していることがわかります.
Scanスキャン
スキャン、すなわち、あるセットのすべての要素に対してfold操作を行いますが、生成されたすべての中間結果を1つのセットに保存します.
練習する val sentence="AAAAAAAAAAAAAABBBBCCCCCDDDDDDD"sentenceの各文字をfoldLeftで1つのArrayBufferに 保存する. val sentence="AAAAAAAAAAAAAABBBBCCCCCDDDDD"マッピングセットを使用して、1つの文の中で、各アルファベットの出現回数 を統計する
高次関数とは、パラメータとして他の関数を使用するか、結果として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折りたたみ
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)
}
}
練習する
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
}
}
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))
}
}