# 11 of scala programming learning - set operation

11.1 mapping map operation of set elements
11.1.1 look at a real demand

Requirement: Please * 2 all elements in List(3,5,7), and return the result in a new collection, that is, return a new List(6,10,14). Please write a program to implement it

11.1.2 using traditional methods to solve

``` //Traditional writing
val list1 = List(3, 5, 7)
var list2 = ListBuffer[Int]()
for (item <- list1) { //ergodic
list2.append(item * 2)
}
println(list2)
```

11.1.3 analysis of traditional methods
1. Simple, easy to understand

Analysis of shortcomings of traditional methods
1. Not concise enough, not conducive to modular programming
2. If we need to process the returned set in the next step, it is not convenient

11.2 map operation

The above question is actually a question about the mapping operation of set elements.
In Scala, it can be solved by map mapping: mapping (transforming) each element in a collection into a new result collection by specifying a function (function), which is actually the so-called transfer of a function as a parameter to another function, which is the feature of functional programming

Take HashSet as an example
1)def map[B](f: (A) ⇒ b): HashSet [b] / / signature of map function
2) This is the map mapping function set type
3)[B] is generic
4)map is a higher-order function (a function that can accept a function, that is, a higher-order function). It can receive the function f: (a) = > B. I'll explain later (briefly introduce next.)
5)HashSet[B] is the new set returned
6) For other sets such as (List,Array,ArrayBuffer )You can also map

11.2.1 use map to solve

```val list1 = List(3, 5, 7)
def f1(n1: Int): Int = {
2 * n1
}
val list2 = list1.map(f1)
println(list2)
```

11.2.2 using scala to simulate map mapping

```object MapOperTheory02 {
def main(args: Array[String]): Unit = {

val list = new MyList
val newList = list.map(f1)
println("newList=" + newList) //List(2,4,6)
}
def f1(n:Int): Int = {
2 * n
}
}

class MyList {

val list1 = List(1,2,3)
var list2 = List[Int]() //empty

//map is a higher-order function, which can accept F: (int) = > int
def map(f:(Int) => Int):  List[Int] = {
//1. Traverse list1
//2. When an element is traversed, it is passed to f
//3. Put the result into a new set
for (item<-list1) {
//filter
list2 = list2 :+ f(item)
}
list2
}

}
```

11.2.3 practice

Please convert all words in val names = List("Alice", "Bob", "Nick") to uppercase and return to the new List set

```object Exercise01 {
def main(args: Array[String]): Unit = {
/*
val names = List("Alice", "Bob", "Nick")
// Thinking analysis
//1. Consider map mapping
//2. You should write a function to convert the traversal elements to uppercase
*/
val names = List("Alice", "Bob", "Nick")
val res = names.map(toUpper)
println("res=" + res)

}
def toUpper(s:String): String = {
s.toUpperCase
}
}
```

11.2.4 flatmap: flatmap is flattening, flattening and flattening map
The basic introduction of flatmap
Flatmap: flatmap is to flatten, flatten and flatten. The effect is to map the sub elements of each element in the set to a function and return a new set.
Case demonstration

```object FlatMapDemo01 {
def main(args: Array[String]): Unit = {
val names = List("Alice", "Bob", "Nick")
val res = names.flatMap(f1)
println("res=" + res)

}
//Convert a String to uppercase
def f1(s:String): String = {
println("s=" + s)
s.toUpperCase
}
}

//Using scala to simulate the operation of flattening

object MapOperTheory02 {
def main(args: Array[String]): Unit = {

val list = new MyList
val newList = list.map(f1)
println("newList=" + newList) //List(2,4,6)

//val names = List("Alice", "Bob", "Nick")

val newList2 = list.flatMap(toUpper)
println("newList2=" + newList2)

}

def f1(n: Int): Int = {
2 * n
}
def toUpper(str:String): String = {
str.toUpperCase
}
}

class MyList {

val list1 = List(1, 2, 3)
var list2 = List[Int]() //empty

val names = List("Alice", "Bob", "Nick")
var list3 = List[Char]() //empty

//map is a higher-order function, which can accept F: (int) = > int
def map(f: (Int) => Int): List[Int] = {
//1. Traverse list1
//2. When an element is traversed, it is passed to f
//3. Put the result into a new set
for (item <- list1) {
//filter
list2 = list2 :+ f(item)
}
list2
}

//Write a map2, simulate a flatMap
def flatMap(f: (String) => String): List[Char] = {

for (item <- names) { // Traverse names.length-1

val temp = f(item)
//Flatten temp
for (i <- temp) {
list3 = list3 :+ i
}

}
list3
}

}
```

11.3 filter of set elements
Filter: put the qualified data (filter) into the new collection

Application case: filter the initials' A 'in the val names = List("Alice", "Bob", "Nick") set to A new set.

If this is done in the traditional way, how can it be done? = "traversal + if judgment"

Case demonstration

```object FilterDemo {
def main(args: Array[String]): Unit = {

val names = List("Alice", "Bob", "Nick")
def startA(s:String): Boolean = {
//Returns true if s starts with 'A'
s.startsWith("A")
}
val names2 = names.filter(startA)  // If startA returns a true, it will be added to the new collection; otherwise, it will be filtered
println("names=" + names2)

}
}
```

11.4 simplification

```object ReduceLeftDemo {
def main(args: Array[String]): Unit = {

val list = List(1, 20, 30, 4, 5)
def sum(n1: Int, n2: Int): Int = {
n1 + n2
}

//Sum with reduceLeft
//Description and introduction
//1. reduceLeft left simplification
//2. reduceLeft can receive a function
//   def reduceLeft[B >: A](@deprecatedName('f) op: (B, A) => B): B
//3. Function OP received by reduceLeft: (B, a) = > B receives two parameters, and returns the result to the first parameter (left parameter) of the next reduceLeft after operation
//4. The running rule (1) first takes two parameters from the left of the list, (2) returns the result to the parameter on the left after the operation, and performs the next operation (3) repeatedly until all elements of the list are traversed

//Specific List(1, 20, 30, 4, 5)
// (((1 + 20 ) + 30) + 4) + 5   = 60
val res = list.reduceLeft(sum)
println("res=" + res)

}
}
```

Second questions
Find the minimum value of List

```object ReduceExercise {
def main(args: Array[String]): Unit = {

/*
The minimum value of List(3,4,2,7,5) is obtained by using the method of simplification
//2min
*/
println(List(3,4,2,7,5).reduceLeft(myMin)) // 2
println(List(3,4,2,7,5).reduceRight(myMin)) // 2

}

def myMin(n1: Int, n2: Int): Int = {
if (n1 > n2) n2 else n1
}
}
```

11.5 fold
11.5.1 basic introduction

1) The fold function continues to pass the value returned in the previous step as the first parameter of the function to participate in the operation until all elements in the list are traversed.

You can think of reduceLeft as a simplified version of foldLeft.
How to understand:
def reduceLeft[B >: A](@deprecatedName('f) op: (B, A) => B): B =
if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft")
else tail.foldLeftB(op)
As you can see, reduceLeft is called foldLeft B , and it starts from the head element of the collection by default.

2) Correlation functions: fold, foldLeft, foldRight, which can be understood by referring to the relevant methods of reduce

11.5.2 case

Look at the following code to see what is output and analyze the reason

```// Fold
val list = List(1, 2, 3, 4)
def minus( num1 : Int, num2 : Int ): Int = {
num1 - num2
}
//Equivalent List(5,1,2,3,4) for operation
// (((5-1) – 2) – 3) – 4 = -5
println(list.foldLeft(5)(minus)) // Currification of function
//Equivalent List(1,2,3,4,5) for operation
// 1-(2- (3- (4-5))) = 3
println(list.foldRight(5)(minus)) //
```

11.5.3 the abbreviations of foldleft and foldRight are: /: and:\

```val list4 = List(1, 9, 2, 8)
def minus(num1: Int, num2: Int): Int = { //function
num1 - num2
}
var i6 = (1 /: list4) (minus) // Equivalent to list4.foldLeft(1)(minus)
println(i6) // Output? -19
i6 = (100 /: list4) (minus)  // Equivalent list4.foldLeft(100)(minus)
println(i6) // Output?
// (1, 9, 2, 8,10) =>  1-(9-(2 -(8 – 10))) = -4
i6 = (list4 :\ 10) (minus) // -4 equivalent list4.foldRight(10)(minus)
println(i6) // Output?
```

11.5.4 scan
11.5.5 basic introduction

Scan, that is, fold all the elements of a collection, but place all the intermediate results in a collection to save
11.5.6 application examples

```object ScanDemo01 {
def main(args: Array[String]): Unit = {
//function
def minus( num1 : Int, num2 : Int ) : Int = {
num1 - num2
}
// (5,1,2,3,4,5) => (5,4, 2,-1,-5,-10)
// Description (1 to 5).scanLeft(5)(minus) execution process
// 1. Put 5 to the left of the set to be operated (5, 1, 2, 3, 4, 5)
// 2. Save the first number to a new set
// 3. Start the operation of left fold [how to operate left fold as mentioned earlier], and put the returned results into a new set
// 4. Finally return the new set (5,1,2,3,4,5) = > (5,4,2, - 1, - 5, - 10)
val i8 = (1 to 5).scanLeft(5)(minus) //
println(i8)

// (1,2,3,4,5) => (3,-2,4,-1,5)
val i10 = (1 to 4).scanRight(5)(minus)
println("i10=" + i10) //

//Look at a case
def add( num1 : Int, num2 : Int ) : Int = {
num1 + num2
}
// (5,1,2,3,4,5)  => (5,6,8,11,15,20)
val i9 = (1 to 5).scanLeft(5)(add) //
println(i9)

}
}
```

11.5.7 classroom exercises

Write the following results:

The result is (3,3,6,18)

11.6 integrated application cases
11.6.1 classroom exercise 1
val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"
Store each character in sentence into an ArrayBuffer through foldLeft
Objective: to understand the usage of flodLeft

```val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"

def putArry( arr : ArrayBuffer[Char], c : Char ): ArrayBuffer[Char] = {
arr.append(c)
arr
}
//Create val arr = ArrayBuffer[Char] () and pass it in as the first parameter
val arr = ArrayBuffer[Char]()
sentence.foldLeft(arr)(putArry)
```

11.6.2 classroom exercise 2
val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"
Use the mapping set to count the number of times each letter appears in a sentence
Tip: Map Char, Int , it is reasonable to use map here
1) How to implement java

```String sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD";
Map<Character, Integer> charCountMap =
new HashMap<Character, Integer>();
char[] cs = sentence.toCharArray();
for ( char c : cs ) {
if ( charCountMap.containsKey(c) ) {
Integer count = charCountMap.get(c);
charCountMap.put(c, count + 1);
} else {
charCountMap.put(c, 1);}}
System.out.println(charCountMap); //ok
```

2) Using scala implementation
Title Requirements:
Val sentence = "aaaaaaaaaaaaaaaabbbbbbbcccddddddd" use the mapping set to count the number of times each letter appears in a sentence: Map Char, Int
Code case

```import scala.collection.mutable

object Exercise03 {
def main(args: Array[String]): Unit = {
/*
val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"
Use the mapping set to count the number of times each letter appears in a sentence
Tip: Map[Char, Int] ()
Requirement: use mapping set to count the number of letters in a sentence

Analytical thinking
1. Use left collapse to determine the first parameter (variable) passed in, use Map[Char,Int]
2. Write a function to handle charcount (map [char, int], C: char): map [char, int] = {}
3. charCount Inside the function, use the operation map + (key - > value) on the map
code implementation

*/

val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"
val map = mutable.Map[Char, Int]()

def charCount(map: mutable.Map[Char, Int], c: Char): mutable.Map[Char, Int] = {
map + (c -> (map.getOrElse(c, 0) + 1))
}

val map2 = sentence.foldLeft(map)(charCount)

println("map2=" + map2)

//The second way of writing

//    val sentence = "AAAAAAAAAABBBBBBBBCCCCCDDDDDDD"
//
//
//    def charCount(map: mutable.Map[Char, Int], c: Char): mutable.Map[Char, Int] = {
//      map + (c -> (map.getOrElse(c, 0) + 1))
//    }
//
//    val map2 = sentence.foldLeft(mutable.Map[Char, Int]())(charCount)
//
//    println("map2=" + map2)

}
}

class Dog {
def say(d:Dog): Unit = {

}
}
```

11.7 extension zipper (merge)
11.7.1 basic introduction
In development, when we need to combine the two sets, we can use zipper.

11.7.2 application examples

```object ZipDemo {
def main(args: Array[String]): Unit = {

// zipper
// Note: if two sets have mismatched elements, they will be discarded
val list1 = List(1, 2, 3)
val list2 = List(4, 5, 6)
val list3 = list1.zip(list2) // (1,4),(2,5),(3,6)
println("list3=" + list3) //(1,4),(2,5),(3,6)

//Ergodic list3 ((1,4),(2,5),(3,6))
for (item <- list3) {
println(item._1 + " " + item._2)
}

}
}
```

11.7.3 precautions for using zip
1) The essence of zipper is the merging operation of two sets. After merging, each element is a dual tuple.
The operation rules are as follows:

3) If the number of two sets does not correspond, the data will be lost.
4) Set is not limited to List, but also other sets such as Array
5) If you want to take out the data of the combined dual tuples, you can traverse

```//Ergodic list3 ((1,4),(2,5),(3,6))
for (item <- list3) {
println(item._1 + " " + item._2)
}
```

11.8 extension iterator
When we need to traverse a collection in while, we need to use iterators
11.8.1 basic description
Get an iterator from the collection through the iterator method, and traverse the collection through the while loop and for expression
11.8.2 application cases

```object IteratorDemo {
def main(args: Array[String]): Unit = {

val iterator = List(1, 2, 3, 4, 5).iterator // Get iterator
println("--------Traversal mode 1 -----------------")
while (iterator.hasNext) { //Determine if there is another one
println(iterator.next())
}
println("--------Traversal mode 2 for -----------------")
val iterator2 = List(11, 22, 33, 44, 55).iterator // Get iterator

for(enum <- iterator2) { //Iterators can also be used in for loops
println(enum) //
}

}
}
```

11.8.3 summary of application cases

1. The construction of iterator is actually an anonymous subclass of AbstractIterator, which provides

/*
def iterator: Iterator[A] = new AbstractIterator[A] {
var these = self
def hasNext: Boolean = !these.isEmpty
def next(): A =
*/

3) The AbstractIterator subclass provides methods such as hasnext next next
4) Therefore, we can use the while method and the hasNext next method variable

11.9 extension Stream
11.9.1 basic description
stream is a collection. This set can be used to store an infinite number of elements. However, the infinite elements will not be produced at one time, but how many intervals they need to use, and they will be produced dynamically. The last element follows the lazy rule (i.e. it needs to use the result to calculate).

11.9.2 create Stream object
Case study:
def numsForm(n: BigInt) : Stream[BigInt] = n #:: numsForm(n + 1)
val stream1 = numsForm(1)

11.9.3 description
1) The data type stored in the stream collection is BigInt
2)numsForm is a custom function whose name is specified by the programmer.
3) The first element of the set created is n, and the rule generated by subsequent elements is n + 1
4) The rules for subsequent element generation can be specified by the programmer, such as numsform (n * 4)

11.9.4 code demonstration and precautions

```object StreamDemo01 {
def main(args: Array[String]): Unit = {

//Description of the code
/*
1.Stream The data type stored in the collection is BigInt
2.numsForm Is a custom function. The function name is specified by the programmer.
3.The first element of the set created is n, and the rule generated by subsequent elements is n + 1
4.The rules for subsequent element generation can be specified by the programmer, such as numsform (n * 4)

*/
def numsForm(n: BigInt) : Stream[BigInt] = n #:: numsForm(n + 1)

val stream1 = numsForm(1) // 1
println("stream1=" + stream1) // (1,?)

//Take out the first element
println(stream1.tail) // (2,?)
println(stream1) //? (1,2,?)

//Note: if the stream set is used, the last attribute cannot be used. If the last set is used, infinite loops will occur

}
}
```
Published 34 original articles, won praise 3, visited 9761

Posted on Tue, 14 Jan 2020 03:33:57 -0500 by ashok_bam