Swift 기초문법

[레인스톤 iOS] 스위프트 easy하게 배워볼까? - 콜렉션 타입(2)

레인스톤 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를 보시면 순서가 뒤섞인 것도 확인하실 수 있습니다.

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

 

끗!

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

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

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

안녕 ~

반응형