[kotlin] 컬렉션 타입과 람다

집합 연산 함수

forEach(), forEachIndexed()

forEach() - 단순히 컬렉션 타입의 데이터 개수만큼 특정 구문 반복 실행

forEachIndexed() - forEach()와 동일하며 람다 함수에 인덱스값까지 전달

    list.filter { it > 10 }
    		.forEach { println(it) }
    listOf(1, 2, 3).forEachIndexed { index, value ->
    	println("index : $index, value : $value") }
    // index : 0, value : 1
    // index : 1, value : 2
    // index : 2, value : 3

all(), any()

all() - 컬렉션 타입의 데이터가 특정 조건에 모두 만족하는지 판단

any() - 컬렉션 타입의 데이터 중 특정 조건에 만족하는 데이터가 있는지 판단

    class User(val name: String, val age: Int)
    var list = listOf(User("Son", 25), User("Lee", 28))
    
    println("all test : ${list.all {it.age > 30}}")
    println("any test : ${list.any {it.age > 30}}")
    
    // false
    // true

count(), find()

count() - 람다식으로 대입한 조건에 만족하는 데이터 개수를 반환

find() - 조건에 만족하는 가장 첫 번째 데이터를 반환

    class User(val name: String, val age: Int)
    var list = listOf(User("Son", 25), User("Lee", 28))
    
    println("count test : ${list.count {it.age > 20}}")
    val user = list.find {it.age > 25}
    println("find test : ${user?.name} ${user?.age}")
    
    // 2
    // Lee 28

reduce(), reduceRight(), fold(), foldRight()

reduce(), fold() - 람다 함수를 대입하면 컬렉션 타입의 데이터를 람다 함수에 차례로 전달하며 람다 함수의 결과값을 반환한다. 반환 값을 기억하고 있다가 그 다음 데이터에 의해 호출될 때 이전 반환 값을 함께 전달해 참조할 수 있도록 한다. 차이는 fold()는 초기값을 지정할 수 있으나 reduce()는 불가능하므로 컬렉션이 비어있으면 런타임 에러가 발생할 수 있다.

reduceRight(), foldRight() - 데이터를 마지막부터 전달하는게 차이.

    result = listOf(1, 2, 3).reduce { sum, next -> sum + next }
    println("$result")
    
    // 6
    result = listOf(1, 2, 3).fold(10, { total, next -> 
    	println("$total ... $next")
    	total + next
    })
    println("$result")
    
    // 10 ... 1
    // 11 ... 2
    // 13 ... 3
    // 16
    
    result = listOf(1, 11, 5).fold(10) { max, next -> 
    	if(next > max) next else max
    }
    println("$result")
    
    // 11

max(), maxBy(), min(), minBy()

max() - 컬렉션 타입의 데이터 중 가장 큰 값을 반환

maxBy() - 람다 함수를 매개변수로 지정하여 로직에 의한 계산 결과중 가장 큰 값을 반환

min() - 컬렉션 타입의 데이터 중 가장 작은 값을 반환

minBy() - 람다 함수를 매개변수로 지정하여 로직에 의한 계산 결과중 가장 작은 값을 반환

    var result: Int? = listOf(1, 11, 5).max()   // 11
    result = listOf(1, 11, 5).maxBy { it % 10 } // 5

none(), sumBy()

none() - 람다 함수에서 지정한 조건에 맞는 데이터가 없으면 true, 있으면 false

sumBy() - 람다 함수를 거쳐 반환한 모든 값을 더하여 반환

    val result = listOf(1, 11, 5).none { it % 10 == 0 } // true
    result = listOf(1, 2, 3).sumBy { it * 10 } // 60

필터링 함수

filter(), filterNot(), filterNotNull()

filter() - 컬렉션 타입의 데이터 중 특정 조건에 맞는 데이터만 추출

filterNot() - filter() 반대

filterNotNull() - null이 아닌 데이터만 추출

    val list = listOf<Int>(12, 8, 9, 20)
    val resultList = list.filter { it > 10 } // 12 20
    
    val map = mapOf<String, Int>("one" to 15, "two" to 5)
    val resultMap = map.filter { entry -> entry.value > 10 } // one 15

drop(), dropWhile(), dropLastWhile()

컬렉션 데이터 중 일부분을 제외하고 나머지를 추출할 때 사용

drop() - 매개변수로 숫자를 대입하면 앞부분부터 대입한 숫자 개수만큼을 제외하고 나머지를 추출

dropWhile() - 매개변수로 람다 함수를 지정하며 앞부분부터 조건에 만족하지 않는 데이터가 나올 때 그 데이터부터 나머지 데이터를 추출하기 시작.

dropLastWhile() - dropWhile()과 반대 순서로 조사하여 데이터 추출.

    listOf(1, 2, 3, 4).drop(2)
    		.forEach { println(it) } // 3 4
    
    listOf(2, 1, 12, 5, 23).dropWhile { it < 10 }
    		forEach { println(it) } // 12 5 23
    
    listOf(2, 1, 12, 5, 4).dropLastWhile { it < 10 }
    		forEach { println(it) } // 2 1 12

slice(), take(), takeLast(), takeWhile()

특정 위치에 있는 데이터를 추출하는 함수

slice() - 범위나 숫자 값을 여러 개 대입하고 그 위치에 있는 데이터만 추출. 인덱스는 0부터 시작.

    listOf(1, 2, 3, 4).slice(1 .. 3)
    		.forEach { println(it) } // 2 3 4
    
    listOf(1, 2, 3, 4).slice(0, 2)
    		.forEach { println(it) } // 1 3

take() - 숫자 값을 매개변수로 전달하면 앞에서부터 숫자에 해당하는 개수의 데이터를 추출.

takeLast() - take()와 반대, 마지막 데이터부터 매개변수로 전달받은 개수만큼 추출.

takeWhile() - 람다 함수로 조건을 명시하고 앞에서부터 차례로 데이터가 조건에 맞는지를 판단, 조건에 맞지 않는 데이터가 나오기 전까지의 데이터를 추출한다.

    listOf(2, 1, 12, 5, 23).take(3)
    		forEach { println(it) } // 2 1 12
    
    listOf(2, 1, 12, 5, 23).takeLast(3)
    		forEach { println(it) } // 12 5 23
    
    listOf(12, 11, 2, 5, 23).takeWhile { it > 10 }
    		forEach { println(it) } // 12 11

매핑 함수

map(), mapIndexed()

map() - forEach()와 비슷하나 단순히 반복 실행이 아닌 결과를 반환한다.

mapIndexed() - map() 함수와 동일한데 람다 함수에 인덱스까지 전달해 준다.

    val list = listOf<Int>(12, 8, 9, 20)
    list.filter { it > 10 }
    		.map { it * 10 }
    		.forEach { println(it) } // 120 200
    
    listOf(1, 2, 3).mapIndexed { index, data -> index * data }
    		.forEach { println(it) } // 0 2 6

groupBy()

groupBy() - 컬렉션 타입의 데이터를 특정 데이터로 묶을 때 사용한다.

inline fun <T, K> Array.groupBy(

keySelector: (T) → K

): Map<K, List>

    list = listOf<User>(User("Son", 24), User("Lee", 28), User("Kim", 28))
    list.groupBy { it. age }
    		.forEach{
    			println("${it. key} ... ${it.value.count()}")
    			it.value.forEach { println("${it.name} ... ${it.age}"}
    		}
    
    // 24 ... 1
    // Son ... 24
    // 28 ... 2
    // Lee ... 28
    // Kim ... 28

요소 함수

contains()

contains() - 컬렉션 타입의 데이터 중 특정 데이터가 있는지를 판단하는 함수로 데이터가 있으면 true, 없으면 false.

    val result = listOf(2, 5, 10, 9).contains(7) // false

elementAt(), elementAtOrElse(), elementAtOrNull()

elementAt() - 특정 위치의 데이터를 추출. IndexOutOfBoundsException 발생 가능

elementAtOrElse() - 특정 위치의 데이터를 추출하지만 IndexOutOfBoundsException 방지. 대신, 지정된 람다 함수가 실행되고 그 람다 함수에서 반환한 값을 반환.

elementAtOrNull() - elementAt() 함수와 동일한데 데이터 범위를 벗어나는 인덱스값을 전달하면 null을 반환.

    val result = listOf(2, 5, 10, 8).elementAt(2) // 10
    result = listOf(2, 5, 10, 8).elementAtOrElse(5, { 0 }) // 0
    val result2: Int? = listOf(2, 5, 10, 8).elementAtOrNull(5) // null

first(), firstOrNull(), last(), lastOrNull()

first() - 람다 함수로 조건을 주고 그 조건에 맞는 가장 첫 번째 데이터를 추출.

firstOrNull() - first() 함수와 동일한데, 만약 조건에 맞는 데이터가 없으면 null 반환.

last() - 람다 함수로 조건을 주고 그 조건에 맞는 가장 마지막 데이터를 추출.

lastOrNull() - last() 함수와 동일한데, 만약 조건에 맞는 데이터가 없으면 null 반환.

    result = listOf(2, 5, 10, 8).first { it % 5 == 0 } // 5
    result = listOf(2, 5, 10, 8).last { it % 5 == 0 } // 10

indexOf(), indexOfFirst(), indexOfLast()

indexOf() - 매개변수로 받은 데이터가 위치하는 첫 번째 인덱스 값을 반환. 데이터가 없으면 -1 반환.

indexOfFirst() - indexOf()와 동일한데, 차이점은 람다 함수를 매개변수로 받는 것.

indexOfLast() - indexOfFirst()와 동일한데, 마지막 인덱스를 반환.

    result = listOf(2, 5, 10, 2).indexOf(2) // 0
    result = listOf(2, 5, 10, 2).indexOfFirst { it % 2 == 0 } // 0
    result = listOf(2, 5, 10, 2).indexOfLast { it % 2 == 0 } // 3

정렬 함수

reversed()

reversed() - 데이터의 순서를 거꾸로 바꾼다.

    listOf(1, 5, 2).reversed()
    		.forEach { println(it) } // 2 5 1

sorted(), sortedBy(), sortedDescending(), sortedDescendingBy()

sorted() - 정렬

sortedBy() - 람다 함수를 대입할 수 있고 람다 함수의 결과값을 대상으로 정렬.

sortedDescending() - 역순 정렬.

sortedDescendingBy() - 람다 함수를 대입할 수 있고 람다 함수의 결과값을 대상으로 역순 정렬.

    listOf(1, 5, 2).sorted()
    		.forEach { println(it) } // 1 2 5
    
    listOf(1, 3, 2).sortedBy { it % 3 }
    		.forEach { println(it) } // 3 1 2