ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [레인스톤 iOS] 스위프트 easy하게 배워볼까? - 콜렉션 타입(2)
    Swift 기초문법 2022. 2. 15. 19:47
    반응형

    안녕하세요!

    iOS개발자로 일하고있는 레인스톤입니다:)

     

    오늘은 콜렉션 타입 2편!

    셋과 사전에 대해서 알아보겠습니다.

     

    셋(set)

    셋에서 가장 중요한 개념은 중복을 허용하지 않는다는 것입니다.

    말이 길어지면 이해가 어렵죠?

    바로 코드부터 보겠습니다.

     

    var todaySet: Set<String> = []
    
    for _ in 0..<10 {
        todaySet.insert("아 오늘 갑자기 넘 춥잖슴~")
    }
    print(todaySet) // ["아 오늘 갑자기 넘 춥잖슴~"]

     

    오... 이제 감이오시나요?

    똑같은 값을 10번이나 넣어줬는데 실제론 하나만 값이 들어가있습니다.

    중복을 허용하지 않는다는 게 어떤 의미인지 확실히 아시겠죠?

    (참고로 콜렉션 타입(1)에서 봤던 배열은 중복된 값이 여러번 들어갈 수 있습니당)

     

    또 하나의 중요한 개념은 순서를 보장하지 않는다는 것입니다.

    이것도 말이 길어지면 복잡하니까 코드를 바로 보겠습니다.

     

    var todaySet: Set<Int> = []
    
    for i in 0..<10 {
        todaySet.insert(i)
    }
    print(todaySet) // [0, 8, 7, 1, 4, 6, 9, 3, 2, 5]

     

    ??? 어떻게 된 일인가요 ???

    0부터 9까지 순서대로 넣어줬는데... 결과는!?

    순서를 보장하지 않는다는 것은 이런 의미입니다:)

    (역시 ~ 참고로 지난 시간에 살펴봤던 배열은 순서를 보장해줍니당)

     

    그렇다면 셋은 언제 필요할까요!?

    순서가 중요하지 않고, 중복된 값을 허용하지 않아야할 때! 사용해주면됩니다.

     

    <알아두면 좋지만 지금은 몰라도 되는 개념>

    셋의 Element는 반드시 hashable이어야만 합니다.

    스위프트에서 String, Int, Double, Bool 등은 기본적으로 hashable입니다.

    hashable이 뭔가요!?

    요걸 이해하기 위해선 hashTable, hash 등 다양한 개념을 먼저 아셔야합니다.

    그래서 아직 모르셔도 됩니다만... 궁금하시다면 swift hashable로 구글링 해보셔도됩니다.

    간!단!하게 설명드리면 정수 해쉬값을 제공하는 Hasher로 해쉬 될 수 있는 타입입니다:)

     

    기본값을 가진 Set 생성하기

     

    var 오늘진짜이상함: Set<String> = ["진짜", "갑자기", "추워짐"]
    var 진짜오늘이상함: Set = ["갑자기", "추워짐", "진짜"]
    
    print(type(of: 오늘진짜이상함)) // Set<String>
    print(type(of: 진짜오늘이상함)) // Set<String>

     

    비어있는 셋을 생성할 때는 '오늘진짜이상함' 변수처럼 타입을 명시해줘야 합니다만?

    기본값을 가진 셋을 생성할 때는 '진짜오늘이상함' 변수처럼 Set만 명시해줘도 Element타입은 추론이 됩니다:)

    (22년 2월 15일 진짜 갑자기 추워졌습니다... 어제는 돌아다닐 때 반팔입었는데...)

     

    Set에 접근하기

     

    셋도 배열처럼 비어있거나 몇 개의 Element를 가지고 있는지 확인이 가능할까요?

     

    var testSet: Set = [1, 2, 3, 4, 5]
    
    if testSet.isEmpty {
        print("비어있다")
    } else {
        print("안비어있다") // 안비어있다
    }
    
    print(testSet.count) // 5

     

    배열과 마찬가지로 isEmpty와 count를 활용하여 각각 비어있는지 여부와 Element의 수를 확인할 수 있습니다!

     

    Set 변경하기

     

    그렇다면 특정 값을 추가, 삭제도 할 수 있겠죠?

     

    var testSet: Set = [1, 2, 3, 4, 5]
    
    testSet.insert(6)
    print(testSet) // [1, 3, 2, 4, 6, 5]
    
    testSet.remove(6)
    print(testSet) // [1, 3, 2, 4, 5]

     

    추가와 삭제 모두 가능합니다.

    참고로 셋의 insert는 배열의 insert와 다릅니다.

    배열에선 insert를 활용할 때 Element와 Index가 필요하지만, 셋에선 Element만 필요합니다.

    시간복잡도 측면에서도 차이를 가지지만...? 요것도 지금은 아실필요 없습니다.

    차근 차근 공부해보자구요 ~

     

    아! 배열과 마찬가지고 셋도 특정 값을 가지고 있는지 확인이 가능합니다.

    (이것도 시간복잡도 측면에서 배열과 다르다는 건 안비밀)

     

    var testSet: Set = [1, 2, 3, 4, 5]
    
    if testSet.contains(6) {
        print("가지고 있다.")
    } else {
        print("가지고 있지 않다.") // 가지고 있지 않다.
    }

     

    이해하기 쉬우시죠!?

    contains를 활용하면 셋이 가지고 있는 Element를 확인할 수 있습니다.

     

    Set 순회하기

     

    var testSet: Set = [1, 2, 3, 4, 5]
    
    for int in testSet {
        print(int)
    }
    
    /*
     2
     1
     5
     3
     4
     */

     

    for-loop를 활용하여 순회도 가능합니다.

    물론 위에서 언급한 것처럼 순서는 보장하지 않습니다!

     

    Set 명령

    • union: 합집합
    • intersection: 교집합
    • subtracting: 차집합
    • symmetricDifference: 대칭차집합
    let oddNumbers: Set = [1, 3, 5, 7, 9]
    let evenNumbers: Set = [2, 4, 6, 8, 10]
    let numbers = oddNumbers.union(evenNumbers)
    
    print(numbers.sorted()) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    print(numbers.intersection(oddNumbers).sorted()) // [1, 3, 5, 7, 9]
    print(numbers.subtracting(oddNumbers).sorted()) // [2, 4, 6, 8, 10]
    print(numbers.symmetricDifference(oddNumbers).sorted()) // [2, 4, 6, 8, 10]

     

    이런식으로 명령을 활용하여 합집합, 교집합, 차집합, 대칭차집합도 구할 수 있습니다!

     

    let oddNumbers: Set = [1, 3, 5, 7, 9]
    let evenNumbers: Set = [2, 4, 6, 8, 10]
    let numbers: Set = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    print(evenNumbers.isSubset(of: numbers)) // true
    print(numbers.isSuperset(of: evenNumbers)) // true
    print(oddNumbers.isDisjoint(with: evenNumbers)) // true

     

    이렇게 Subset이나 Superset 여부도 확인할 수 있습니다.

    isDisjoint(with:)의 경우 서로 같은 값이 없을 때 true를 반환합니다.

     

    사전(Dictionary)

    사전도 배열, 셋과 마찬가지로 타입을 축약해서 선언할 수 있습니다.

    빈 딕셔너리를 만들어볼까요?

     

    var dict: Dictionary<String, Int> = [:]
    var dict2: [String: Int] = [:]
    
    print(type(of: dict)) // Dictionary<String, Int>
    print(type(of: dict2)) // Dictionary<String, Int>

     

    dict의 형식을 [Key: Value]의 형태로 축약해서 나타낸 것이 dict2 입니다.

    물론 이렇게 빈 사전에 값을 넣어줄 수도 있습니다.

     

    var dict: [String: Int] = [:]
    
    dict["one"] = 1
    
    print(dict["one"]!) // 1

     

    key 값을 정해주고 해당 key 값에 원하는 value를 넣어주면 됩니다.

    여기서도 왜 느낌표(!)가 있는지는 모르셔도 됩니다.

    지난번에 말씀드린 것처럼 옵셔널 파트에서 차차 살펴볼 예정입니다.

     

    기본값을 가진 사전 생성하기 & 변경하기

     

    var capitalCity = ["한국": "서울", "미국": "뉴욕", "영국": "런던"]
    
    capitalCity["미국"] = "워싱턴, D.C."
    
    print(capitalCity["미국"]!) // 워싱턴, D.C.

     

    기본값을 생성하고 보니 미국의 수도를 틀려버렸네요...

    이럴 땐 key값으로 접근해서 value값을 수정해줄 수 있습니다.

    참 ~ 쉽죠!?

     

    아 참참!

    사전도 셋과 마찬가지로 중복을 허용하지 않고, 순서를 보장하지 않습니다:)

     

    var capitalCity = ["한국": "서울", "미국": "뉴욕", "영국": "런던"]
    
    capitalCity["미국"] = "워싱턴, D.C."
    capitalCity["미국"] = "워싱턴"
    print(capitalCity["미국"]!) // "워싱턴"
    
    print(capitalCity) // ["영국": "런던", "한국": "서울", "미국": "워싱턴"]

     

    미국이라는 key값이 여러번 들어가지 않고 가장 최근에 수정한 값으로 바뀌는 것 보이시죠?

    중복된 key값을 허용하지 않기 때문입니다.

     

    또한 가장 마지막 줄 print를 보시면 순서가 뒤섞인 것도 확인하실 수 있습니다.

    사전도 셋과 같이 순서를 보장해주지 않습니다!

     

    끗!

    우와 ~ 콜렉션 타입까지 알아봤습니다.

    쉬우면 쉽고 어려우면 어렵다고 느끼셨을 수도 있을텐데요.

    이해되지 않는 부분은 코멘트 남겨주시면 답변드리겠습니다:)

    안녕 ~

    반응형

    댓글

Designed by Tistory.