본문 바로가기
개발 관련 공부/코틀린

Unit3-1(1)

by 슴새 2022. 9. 13.
반응형
이 포스트는 2021.12~2022.09 기간동안 벨로그에 작성한 글을 티스토리에 옮겨 적은 것입니다.

collection

컬렉션은 단어 목록이나 직원 기록 모음과 같은 관련 항목 그룹이다. 컬렉션의 항목은 순서가 지정되거나 지정되지 않을 수 있으며 고유하거나 고유하지 않을 수 있다. 목록 역시 컬렉션의 한 유형이다.

set

Kotlin의 또 다른 컬렉션 유형은 집합이다. 목록과 달리 중복된 원소를 가질 수 없다.

val numbers = listOf(0, 3, 8, 4, 0, 5, 5, 8, 9, 2)
println("list:   ${numbers}")
println("sorted: ${numbers.sorted()}")
val setOfNumbers = numbers.toSet()
println("set:    ${setOfNumbers}")

실행결과

list:   [0, 3, 8, 4, 0, 5, 5, 8, 9, 2]
sorted: [0, 0, 2, 3, 4, 5, 5, 8, 8, 9]
set:    [0, 3, 8, 4, 5, 9, 2]

목록을 toSet()을 이용하여 집합으로 바꾸자 중복된 원소가 저절로 사라졌다.

또한 집합은 순서가 없다.

val set1 = setOf(1,2,3)
val set2 = mutableSetOf(3,2,1)
println("$set1 == $set2: ${set1 == set2}")

실행 결과

[1, 2, 3] == [3, 2, 1]: true

집합에서 할 수 있는 기본 작업 중 하나는 contains() 함수를 사용하여 특정 항목이 집합에 속하는지 여부를 확인하는 것이다.

println("contains 7: ${setOfNumbers.contains(7)}")

이외에도 교집합(∩) 또는 합집합(∪)과 같은 연산을 intersect() 또는 union()을 사용하여 실행할 수 있다.

Map

맵 또는 사전 역시 컬렉션 유형의 하나이다. 맵은 특정 키가 부여된 값을 쉽게 찾을 수 있도록 설계된 키-값 쌍의 집합이다.

fun main() {
    val peopleAges = mutableMapOf<String, Int>(
        "Fred" to 30,
        "Ann" to 23
    )
    println(peopleAges)
    
    //항목을 더 추가하려는 경우
    peopleAges.put("Barbara", 42)
    //혹은
    peopleAges["Joe"] = 51
}

실행결과

{Fred=30, Ann=23, Barbara=42, Joe=51}

이미 있는 키 쌍에 대한 값을 업데이트할 수도 있다.

peopleAges["Fred"] = 31 //이제 프레드의 나이는 31살

forEach

컬렉션의 모든 객체를 열거하는 것은 일반적인 작업이므로, Kotlin에서는 자동으로 모든 항목을 탐색한 후 항목별로 작업을 실행하는 forEach()를 제공한다.

peopleAges.forEach { print("${it.key} is ${it.value}, ") }

실행결과

Fred is 31, Ann is 23, Barbara is 42, Joe is 51,

forEach는 현재 항목의 변수를 지정하는 대신 특수 식별자 it을 사용한다.

map

위에서 나온 Map과는 다름!
map 함수는 컬렉션의 각 항목에 변환을 적용한다.

위의 forEach 실행결과에서 마지막에 붙은 쉼표를 없애기 위해..

println(peopleAges.map { "${it.key} is ${it.value}" }.joinToString(", ") )

실행결과

Fred is 31, Ann is 23, Barbara is 42, Joe is 51

peopleAges.map은 peopleAges의 각 항목에 변환을 적용하고 변환된 항목으로 이루어진 새 컬렉션을 만든다.

중괄호 {} 안에 있는 부분은 각 항목에 적용할 변환을 정의합니다. 키-값 쌍을 가져와서 문자열로 변환한다. 예를 들어 <Fred, 31>을 Fred is 31로 변환된다.

joinToString(", ")은 변환된 컬렉션의 각 항목을 문자열에 추가하고 ,로 구분하며 마지막 항목에는 기호를 추가하지 않는다.

이 모든 과정은 점 연산자(.)로 결합된다.

filter

컬렉션의 또 다른 작업은 특정 조건과 일치하는 항목을 찾는 것이다. filter() 함수는 컬렉션에서 표현식을 기반으로 일치하는 항목을 반환한다.

filter 호출에는 괄호가 필요 없으며, it은 목록의 현재 항목을 나타냅니다.

val filteredNames = peopleAges.filter { it.key.length < 4 }
println(filteredNames)

실행결과

{Ann=23, Joe=51}

람다

앞에서 배운 코드

peopleAges.forEach { print("${it.key} is ${it.value}") }

forEach 다음에 매개변수가 포함된 괄호를 사용하는 대신 함수 이름 다음에 코드를 포함하는 중괄호 {}를 사용한 것을 볼 수 있다. map이나 filter도 마찬가지이다.
중괄호 안에 작은 함수를 작성하는 것과 같지만 함수 이름은 없다. 이렇게 이름이 없으며 곧바로 표현식으로 사용할 수 있는 함수는 아주 유용한 개념으로, 람다 표현식 또는 간략하게 람다라고 한다.


예를 들어 매개변수에 3을 곱해서 반환하는 람다 표현식을 정의하고, 이 함수를 변수 triple에 넣으면 위와 같다. (Int)->Int 는 함수의 타입을 정의하는데, 매개변수로 int가 들어가고 반환값이 int 라는 뜻이다.

fun main() {
    val triple: (Int) -> Int = { a: Int -> a * 3 }
    println(triple(5)) //실행결과: 15
}

매개변수의 명시적인 선언(a: Int)을 생략하고 함수 화살표(->)를 생략하고 함수 본문만 사용할 수도 있다.

val triple: (Int) -> Int = { it * 3 }

고차함수

고차함수는 함수(이 경우에는 람다)를 다른 함수로 전달하거나 다른 함수에서 함수를 반환하는 것을 의미한다. map, filter, forEach 함수는 모두 매개변수로 함수를 사용했으므로(프린트문, if문 등) 고차 함수의 예이다.

문자열 목록을 사전식 정렬하려면 내장된 sorted() 메서드를 컬렉션에 사용하면 된다. 그러나 문자열 길이를 기준으로 목록을 정렬하려면 두 문자열의 길이를 가져와 비교하는 코드를 작성해야 한다. Kotlin에서는 람다를 sortedWith()메서드에 전달하여 작성할 수 있다.sortedWith() 역시 고차함수의 예이다.

println(peopleNames.sortedWith { str1: String, str2: String -> str1.length - str2.length })

string 2개가 매개변수로 들어가는 이유는, 두 객체의 길이를 비교하여 뭐가 더 짧은 이름인지 알기 위해서이다. 이렇게 해주면 sortedWith은 필요한 모든 비교연산을 알아서 수행하고 이름 길이가 짧은 순으로 오름차순 정렬 해준다.

파이썬이면 peopleNames.sort(key=len) 하나면 끝날일을..떼잉..

반응형

'개발 관련 공부 > 코틀린' 카테고리의 다른 글

Unit 3-1(2)  (0) 2022.09.14
Unit 3-1(2)  (0) 2022.09.14
Unit2-3  (1) 2022.09.13
Unit2-2  (0) 2022.09.13
Unit2-1  (0) 2022.09.13

댓글