32YB SOPT/swift 문법 스터디

[SOPT] 야우쓰_4주차 (컬렉션 타입, array, dictionary, set, 값타입, 참조타입)

신_이나 2023. 5. 17. 13:26

 

 

 

야우쓰란? "야 우리도 스위프트 할 수 있어"

in SOPT iOS

 

 

 

 

 

 

 

 

4주차의 키워드는 컬렉션 타입이다.

 

 

 

- 컬렉션 타입 (Collection Types)

 컬렉션타입(collection types)이란 이름 그대로 데이터를 수집한다는 의미이다. array, set, dictionary 이렇게 3가지 타입을 지원한다. 

 

- 배열 (Array)

배열은 [element] 로 사용할 수 있으며, 아래와 같이 선언할 수 있다. 또한 값을 추가할 때는 append 를 사용하여 추가한다.

 

//배열 선언

var jiwon = [Int]() //var 로 선언해야 값 변경 가능
jiwon.append(3)
//Prints [3]

//특정 위치에 삽입하고 싶다면 insert 를 사용한다
//ex) jiwon.insert(0, at:0)

jiwon = []
//Prints []

 

위 코드에서는 배열을 초기화 해줄 때 직관적으로 [ ] 를 써주었다. nil 로 초기화 뿐만 아니라 특정 값으로 초기화해줄 수 있다. 뿐만 아니라 배열을 합칠 수도 있다.

//특정 값으로 배열 초기화
var jiwon = Array(repeating: 1, count: 2)
//Prints [1, 1]

//배열끼리 합
var shin = Array(repeating: 2, count: 2)
shin = jiwon + shin
//Prints [1, 1, 2, 2]
//배열을 더하는 순서에 따라 배열의 요소의 순번이 바뀌었다

 

배열의 개수를 셀 때는 count 를 사용한다.

//배열 개수 
var jiwon = Array(repeating: 1, count: 2)
var jiwonCount = jiwon.count
//Prints 2

 

배열에서 값을 제거하고 그 값을 저장할 수 있다. 

//특정 위치에 원소 삭제하고 그 값을 저장
var jiwon = ["tteok", "bok", "ki"]
var removewon = jiwon.remove(at: 0)
//Print tteok

var firstjiwon = jiwon.removeFirst()
//Print bok

var lastjiwon = jiwon.removeLast()
//Print ki

 

만약 값을 저장하고 싶지 않다면 아래 방법들로 배열을 제거할 수 있다.

//범위를 설정하여 제거
var jiwon = ["tteok", "bok", "ki"]
jiwon.removeSubrange(1...2)
//jiwon-Prints ["tteok"]

//마지막 값을 옵셔널의 형태로 반환하며 삭제
//삭제하는 값 자체는 옵셔널로 반환하지만 굳이 popLast 를 받는 변수를 선언하지 않아도 된다.
var shin = jiwon.popLast()
//shin-Prints Optional("tteok")
//jiwon-Prints []

 

배열에서 찾으려는 값의 인덱스를 얻을 수도 있고, 특정 값을 포함하는지 알 수도 있다.

var jiwon = ["tteok", "bok", "ki"]
print(jiwon.firstIndex(of: "bok"))
//Prints Optional(1)

print(jiwon.contains("bok"))
//Prints true

 

배열을 순회할 때는 for-in loop 를 사용하여 순회할 수 있다.

 

 

- 셋 (Set)

set 의 선언과 삽입 또한 배열과 비슷하다. 하지만 삽입할 때 요소들의 순서가 정해져있지 않아 중간에 삽입될 수도 있다.

var jiwon: Set = ["tteok", "bok", "ki"]
jiwon.insert("joA")
//Prints ["bok", "joA", "ki", "tteok"]

 

set이기 때문에 집합! 을 표현할 수 있다.

let oddset: Set = [1,3,5,10]
let evenset: Set = [2,4,6,10]

//두 집합 더하기
var a = oddset.union(evenset).sorted()
//Prints [1, 2, 3, 4, 5, 6, 10]

//교집합
var b = oddset.intersection(evenset).sorted()
//Prints [10]

//차집합
var c = oddset.subtracting(evenset).sorted()
//Prints [1, 3, 5]

//대칭차집합
var d = oddset.symmetricDifference(evenset).sorted()
//Prints [1, 2, 3, 4, 5, 6]

 

set 은 공통값이 있는지 비교를 할 수 있다.

let Aset: Set = [1,3,5,10]
let Bset: Set = [1,3]

//Bset이 Aset을 subset 으로 가지고 있는가 = false
//반대는 성립
print(Aset.isSubset(of: Bset)) //false
print(Bset.isSubset(of: Aset)) //true

//Bset이 Aset을 superset(부모셋) 으로 가지고 있는가 = true
print(Aset.isSuperset(of: Bset)) //true

//isDisjoint 어떠한 교집합도 없을 때 true
print(Aset.isDisjoint(with: Bset)) //false

 

 

 

- 사전 (Dictionary)  사전아닌가?딕셔너리라고해야되나?푸하핳ㅇ

[Key: Value] 형태로 Dictionary 를 선언해 사용할 수 있다. 따라서 key와 value 가 함께 저장되는 자료구조다. set 과 마찬가지로 정렬되지 않은 컬렉션이며, 값은 중복가능하지만 키는 중복해서는 안된다. 당연하게 key끼리, value 끼리의 자료형은 모두 같아야 한다.

//타입 추론으로는 생성 불가능
var jiwon: [Int: String] = [1: "shin", 2: "jiwon"]
var shin = Dictionary<Int,String>()

 

요소에 접근해보자! 옵셔널 값으로 반환된다.

var jiwon: [Int: String] = [1: "shin", 2: "jiwon"]
let a = jiwon[1]
let b = jiwon[2]
print(a) //Optional("shin")
print(b) //Optional("jiwon")

 

아래와 같은 방법들로 요소를 추가할 수 있다. 또한 마찬가지로 index의 순서는 정해져있지 않다.

var jiwon: [Int: String] = [1: "shin", 2: "jiwon"]
jiwon[3] = "is"
jiwon[4] = "gorgeous"

jiwon.updateValue("haha", forKey: 5)

print(jiwon) //[1: "shin", 5: "haha", 3: "is", 2: "jiwon", 4: "gorgeous"]

 

요소를 삭제할 수 있다.

var jiwon: [Int: String] = [1: "shin", 2: "jiwon"]
jiwon[1] = nil //[2: "jiwon"]
jiwon.removeValue(forKey: 2) //[:]

//한 번에 모두를 삭제하는 방법도 있다.
jiwon.removeAll()

 

그렇다면 비교해보자,,!

자료형 \ 특징 순서 요소 중복
Array O index 중복 가능
Set X key 중복 불가
Dictionary X key & value 중복 불가
Tuple O - 중복 가능 + 변경 불가능

 

 

- 값타입과 참조타입 (Value Type and Reference Type)

값타입은 값 자체를 변수명과 함께 스택에 저장하고, 참조 타입은 값은 별도의 메모리에 저장하고 주소값을 스택에 저장한다. 따라서 컬렉션타입은 값타임이라고 할 수 있다. Swift 는 주소값보단 값 자체를 저장하는 값타입이 다른 언어보다 특화되어 있다고 한다. 값타입을 선언할 때는 struct 를 사용하고, 참조 타입을 선언할 때는 class 를 선언한다. 참조타입의 대표적인 것이 closure 인데, 값 자체를 전달하는 것이 아닌 참조만 공유하는 것이다. 그렇다면 delegate 도 reference type 이겠다!

 

 

 

Q.“Swift에서는 컬렉션 타입들이 모두 제네릭 컬렉션으로 구현되어 있다”

A. YES!

 

generic 이란 야우쓰 3주차에서 언급한 적있다. 그 당시에는 " 타입에 의존하지 않는 타입으로 범용 코드를 작성할 때 사용 가능하다." 라고 작성하였는데, 컬렉션 타입에서 사용하는 예시로 더 쉽게 말하자면, 여러 가지 데이터 타입들을 담을 수 있다는 의미다. 한마디로 한 가지의 배열/set/dictionary 에 int,string,char 등등을 종류의 제약없이 한 가지 골라 넣을 수 있다는 뜻이다.