Filter
filter篩選
it是list的元素,元素中有a的字母,加到新的list中,把新的list作為傳回值傳回。
1
2
3
4
5
fun main() {
val list = listOf<String>("Mary", "Bill", "Alex", "Ben")
.filter { it.contains("a") }
println(list)
}
filter擴展函式
filter擴展函式,參數是predicate Lambda,把新的list作為傳回值傳回。
filter會建立新的ArrayList
1
2
3
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
return filterTo(ArrayList<T>(), predicate)
}
filterTo擴展函式
filterTo用來遍歷所有元素,並把每個元素作為參數,傳入predicate Lambda。
有符合predicate Lambda條件的元素,才把元素加入要傳回的destination List中。
1
2
3
4
5
6
7
8
9
10
public inline fun <T, C : MutableCollection<in T>> Iterable<T>.filterTo(destination: C, predicate: (T) -> Boolean): C {
// 遍歷所有元素
for (element in this) {
// 把每個元素作為參數,傳入predicate Lambda
if (predicate(element)) // 若為true
// element 加入 destination List
destination.add(element)
}
return destination
}
重要的是下面這段程式
1
2
3
4
5
6
7
// 遍歷所有元素
for (element in this) {
// 若為true
if (predicate(element))
// element 加入 destination List
destination.add(element)
}
predicate Lambda
predicate Lambda的傳回值為true或false,若為true就加到傳回值destination List中。
T參數為集合中的每一個元素。
1
predicate: (T) -> Boolean
number為每個元素的參數,因為參數只有一個,可以省略,用it代替number。
true是傳回值,若為true就加到傳回值List中。
1
2
3
4
5
val nums = listOf(7, 5, 4, 3, 22, 11, 18)
.filter { number ->
true
}
println(nums)
[7, 5, 4, 3, 22, 11, 18]
若為false,若為false就不加到傳回值List中。
最終沒有任何元素加入List。
1
2
3
4
5
val nums = listOf(7, 5, 4, 3, 22, 11, 18)
.filter { number ->
false
}
println(nums)
[]
range與filter
range本身不會產生List,range.filter(),filter本身就會傳回新的List。
以下程式碼是:產生2到7之間可以被2整除的數,傳回List。
{it % 2 == 0}
這段程式碼是filter predicate Lambda,元素有符合條件,才可以被加入到List中。
1
2
3
4
5
6
val range = 2 ..7
// 參數只有一個,可以省略參數,用it代替參數
// it代表range中的每一個元素
// it % 2 == 0 元素可以被2整除,餘數為0,才可以加入List中
val list = range.filter { it % 2 == 0 }
println(list)
[2, 4, 6]
以下寫法與上面相同。
1
2
3
// range 遇到filter會產生list
val list = (2 .. 7).filter { it % 2 == 0 }
println(list)
[2, 4, 6]
傳回二維陣列中有red的元素
flatMap可以把二維陣列變成一維陣列。
若元素有包含red,把它加入到陣列中。
1
2
3
4
5
6
7
fun main() {
val list = listOf(
listOf("red apple", "black dog", "red fish"),
listOf("red car", "blue sky", "blue car"))
.flatMap { it.filter { it.contains("red") } }
println(list)
}
[red apple, red fish, red car]
it是一維的List。
1
it.filter { it.contains("red")
可以看成以下這樣的程式碼。
it換成一維的List。
1
2
3
listOf("red apple", "black dog", "red fish").filter {
it.contains("red")
}
元素中有red的字串,符合這個條件,才加到新的list中,filter會傳回新的list。
1
2
3
4
5
val filterList = listOf("red apple", "black dog", "red fish")
.filter {
it.contains("red")
}
println(filterList)
[red apple, red fish]
質數
質數只能被1與自己整除。
1
2
3
4
5
6
7
8
fun main() {
val nums = listOf(7, 5, 4, 3, 22, 11, 18)
val prime = nums.filter { number ->
(2 until number).map { number % it }
.none{ it == 0}
}
println(prime)
}
[7, 5, 3, 11]
條件
符合條件才會加到filter的List中。
1
2
(2 until number).map { number % it }
.none{ it == 0}
產生2到(number - 1)的數字
1
(2 until number)
number為nums中的每個元素,產生2到(number - 1)的數字,until是不包含number。
因為質數只能被1與本身整除,先要判斷是不是質數。
假設number = 8
要判斷8是不是質數,要從2到7(不包含8)的數字中尋找可被整除的數字,若在這個範圍內找到可以整除8的「除數」,代表8不是質數。
為何範圍是2到7,因為質數只能被1與本身的數字整除,要先排除掉1與本身能整除的數,若在2到7的範圍內,可以被2 .. 7 任何一個數字整除,代表不是質數。
list存放餘數
map,會傳回跟原本集合一樣大小的集合。
以下這段程式碼,假設number = 8。
it為2到(number - 1)的數字。
1
(2 until number).map { number % it }
例:number 為 8
1
number % it
產生的餘數如下:
8 % 2 = 0
8 % 3 = 2
8 % 4 = 0
8 % 5 = 3
8 % 6 = 2
8 % 7 = 1
map傳回新的list,把以上的餘數都放入list中。
1
2
val list = (2 until 8).map { 8 % it}
println(list)
[0, 2, 0, 3, 2, 1]
none
擴展函式,this就是List,遍歷List每個元素,判斷是否符合predicate匿名函式()的條件,符合就傳回「false」。
1
2
3
4
5
public inline fun <T> Iterable<T>.none(predicate: (T) -> Boolean): Boolean {
if (this is Collection && isEmpty()) return true
for (element in this) if (predicate(element)) return false
return true
}
重點在以下這個程式碼,若predicate Lambda傳回值為「true」,就「返回false」。
1
if (predicate(element)) return false
若list中有餘數是0,代表可以被整除,Lambda傳回值為true,none()就返回false。
1
.none{ it == 0}
filter過濾false的元素
predicate Lambda會傳回true或false,若為true就加到傳回值List中。
若為false,就不加入傳回值List中。
1
2
3
4
5
6
7
8
9
fun main() {
val nums = listOf(7, 5, 4, 3, 22, 11, 18)
val prime = nums.filter { number ->
// 質數程式碼最後傳回true 或 false,若為true就加入新list
// 若為false就不加入新list
false
}
println(prime)
}
質數2
寫一個擴展函式,判斷數字是不是質數。
1
2
3
4
5
6
7
8
fun Int.isPrime(): Boolean {
for (i in 2 until this) {
if (this % i == 0) {
return false
}
}
return true
}
寫一個程式,判斷1 .. 5000之間有多少個質數,取前面10個質數出來。
1
2
3
4
fun main() {
val list = (1 .. 5000).filter { it.isPrime() }.take(10)
println(list)
}
[1, 2, 3, 5, 7, 11, 13, 17, 19, 23]
take()
集合中,取出多少個元素。
take()擴展函式(僅寫出重要部分)
1
2
3
4
5
6
7
8
9
10
11
// 計數器
var count = 0
// 新的list
val list = ArrayList<T>(n)
for (item in this) {
// 加入元素
list.add(item)
// 若取出數量 == n,就離開迴圈。
if (++count == n)
break
}
Sequence序列
序列是使用時才會產生,不會先建立一個List,占住記憶體空間。
產生從2開始,每個數字加+1,產生20個,產生2、3、4 … 19、20、21,共20個數字。
generateSequence(2),參數名為seed,也就是種子,從2開始。
以下程式碼,當呼叫take(20),才會真正產生序列的物件,建立20個元素。
1
2
val sequence = generateSequence(2){ value -> value + 1 }.take(20)
println(sequence.toList())
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
value就是從種子2,每一個step都是+1,在此步驟開始產生序列物件,每遍歷一次產生一個元素。
1
{ value -> value + 1 }
以下程式碼,從2開始,產生20個質數。
先判斷數字是質數,才開始產生序列元素,直到元素達到20個。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fun Int.isPrime(): Boolean {
for (i in 2 until this) {
if (this % i == 0) {
return false
}
}
return true
}
fun main() {
val sequence = generateSequence(2){ value -> value + 1 }
.filter { it.isPrime() }
.take(20)
println(sequence.toList())
}
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]