[Swift] Tuple & Collection Types

비나·2022년 8월 21일

Swift

목록 보기
3/8
post-thumbnail

📌 Tuple

Tuple이 무엇인지 위키피디아에서 찾아보면 다음과 같다.

튜플(tuple)은 셀 수 있는 수량의 순서 있는 열거이다.

Swift에서 Tuple은 지정된 데이터 묶음을 의미한다.
사용자는 자기 마음대로 튜플의 타입을 지정할 수 있다.
파이썬 튜플과 매우 유사하다.
사실 내가 파이썬을 해본 적은 없고 예전에 친구가 파이썬 과제를 물어봤을때 찾아봤던 기억이 난다.
근데 책에도 파이썬 튜플과 유사하다고 나와있는걸 보니 유사한게 맞는 듯하다.

✅ 특징

  1. 타입 이름이 없음
  2. 일정 타입 나열로 튜플 타입 생성 가능
  3. 튜플에 포함되는 데이터 개수는 마음대로 가능

✅ 예제

다음은 사람의 이름을 String 타입으로, 나이를 Int 타입으로 받는 튜플 예제이다.

var person: (String, Int) = ("Vina", 23)

튜플의 값을 빼오는 것은 다음과 같이 인덱스를 통해서 할 수 있다.

📄 입력

import UIKit

var person: (String, Int) = ("Vina", 23)
print("Her name is \(person.0) and she is \(person.1) years old.")

💻 출력
Her name is Vina and she is 23 years old.

위와 같은 예제의 경우 튜플은 각 요소를 이름 대신 숫자로 표현하여 간편해보인다.
그러나 다른 프로그래머가 코드를 본다면 각 요소가 어떤 의미를 갖는지 유추하기 어렵다.
-> 요소마다 이름을 붙여주면 파악이 쉬워진다.

각 요소에 이름을 붙여주면 다음과 같이 예제를 바꿀 수 있다.

📄 입력

import UIKit

var person: (name:String, age:Int) = ("Vina", 23)
print("Her name is \(person.name) and she is \(person.age) years old.")

💻 출력
Her name is Vina and she is 23 years old.

결과는 동일한 것을 볼 수 있다.
이름을 붙여주었더라도 기존과 같이 인덱스를 이용하여 값을 빼오는 것도 가능하다.



📌 Collection Types

Swift는 Tuple 외에 많은 수의 데이터를 묶어서 저장하고 관리할 수 있는 Collection Types을 제공한다.
Collection Types에는 Array(배열), Dictionary(딕셔너리), Set(세트) 등이 있다.

✅ Array

Array(배열)은 같은 데이터 타입의 데이터를 일렬로 나열한 후 순서대로 저장하는 형태이다.
배열을 선언하는 방법은 아래와 같이 Array<datatype> 이다.

// 사람 이름 목록 String 배열
var people: Array<String> = ["Vina","Mei","Hoho","Coco"]
// 비어있는 String 배열
var emptyArray: Array<String> = Array<String>()

아니면 아래와 같이 Array<datatype> 의 축약형으로 [datatype]을 써도 된다.

// 사람 이름 목록 String 배열
var people: [String] = ["Vina","Mei","Hoho","Coco"]
// 비어있는 String 배열
var emptyArray: [String] = [String]()
// 배열의 데이터 타입이 정확히 명시된 경우 빈 배열은 아래처럼도 가능
var emptyArray2: [String] = []

✅ Array Properties & Method

배열에 사용할 수 있는 프로퍼티들과 메서드를 살펴보자.

📖 isEmpty

isEmpty 프로퍼티를 통해 배열이 비어있는지 아닌지 확인할 수 있다.
예제를 보면 다음과 같다.

📄 입력

import UIKit

var people: [String] = ["Vina","Mei","Hoho","Coco"]
var emptyArray: Array<String> = Array<String>()
var emptyArray2: [String] = []

print(people.isEmpty)
print(emptyArray.isEmpty)

💻 출력

false
true

📖 count

count 프로퍼티를 통해 배열에 몇개의 요소가 존재하는지 알 수 있다.
예제는 다음과 같다.

📄 입력

import UIKit

var people: [String] = ["Vina","Mei","Hoho","Coco"]
var emptyArray: Array<String> = Array<String>()
var emptyArray2: [String] = []

print(people.count)
print(emptyArray.count)

💻 출력

4
0

📖 firstIndex(of:)

firstIndex(of:) 메서드를 사용하여 해당 요소의 인덱스를 알아낸다.
중복 요소가 있는 경우 제일 먼저 발견된 요소의 인덱스 값을 반환한다.

📄 입력

var people: [String] = ["Vina","Mei","Hoho","Coco"]
print(people.firstIndex(of: "Mei"))
print(people.firstIndex(of: "Vina"))

💻 출력

1
0

📖 first, last

배열의 처음과 마지막 요소를 가져올때 사용한다.

📄 입력

import UIKit

var people: [String] = ["Vina","Mei","Hoho","Coco"]
print(people.first)
print(people.last)

💻 출력

"Vina"
"Coco"

📖 append(_:), insert(_:at:), remove(_:)

append(_:) : 배열 맨 뒤에 요소 추가
insert(_:at:) : 배열 중간에 요소 추가
remove(_:) : 배열의 요소 삭제 후 반환

✨ append(_:) 예제

import UIKit

var people: [String] = ["Vina","Mei","Hoho","Coco"]
people.append("Momo")
people.append(contentsOf: ["Lala", "Jojo"])

// => ["Vina", "Mei", "Hoho", "Coco", "Momo", "Lala", "Jojo"]

✨ insert(_:at:) 예제

import UIKit

var people: [String] = ["Vina","Mei","Hoho","Coco"]
people.insert("Momo", at: 0)
people.insert(contentsOf: ["Lala", "Jojo"], at: 2)

// => ["Momo", "Vina", "Lala", "Jojo", "Mei", "Hoho", "Coco"]

✨ remove(_:) 예제

import UIKit

var people: [String] = ["Vina","Mei","Hoho","Coco"]

let removeFirst = people.removeFirst()	// "Vina" 제거
let removeLast = people.removeLast()	// "Coco" 제거
let removeIndexZero = people.remove(at: 0) // "Mei" 제거

// => ["Hoho"]

✅ Dictionary

Dictionary(딕셔너리)는 요소들이 순서 없이 키와 값의 쌍으로 구성된다.
내가 공부하는 책에 나와있는 딕셔너리의 특징을 보면 다음과 같다.

  1. 딕셔너리의 저장 값은 항상 키와 쌍을 이룬다.
  2. 딕셔너리 안에는 키가 하나이거나 여러 개일 수 있다.
  3. 각 값에 키로 접근할 수 있다.
  4. 하나의 딕셔너리 안의 키는 같은 이름을 중복할 수 없다.
    -> 딕셔너리에서 키는 값을 대신하는 유일한 식별자이다.
    -> 반면에 딕셔너리에서 값은 유일하지 않다.

딕셔너리를 선언하는 방법은 아래와 같이 Dictionary<키datatype, 값datatype> 이다.

// 아스키 코드 Int, Character 딕셔너리
var ascii: Dictionary<Int, Character> = [65: "A", 66: "B", 67: "C", 68: "D"]
// 비어있는 Int, Character 딕셔너리
var ascii: Dictionary<Int, Character> = Dictionary<Int, Character>()

아니면 아래와 같이 Dictionary<키datatype, 값datatype> 을 축약하여 `[키datatype: 값datatype]으로 나타낼 수도 있다.

var ascii: [Int: Character] = [65: "A", 66: "B", 67: "C", 68: "D"]
// 비어있는 Int, Character 딕셔너리
var ascii: [Int: Character] = [String: Int]()
// 딕셔너리의 데이터 타입이 정확히 명시된 경우 빈 배열은 아래처럼도 가능
var ascii: [Int: Character] = [:]

📖 값 추가 / 변경

값을 추가하거나 변경할때는 프로퍼티나 메서드를 쓰지 않아도 된다.
아래와 같이 해주면 된다.

📄 입력

import UIKit

var emptyDictionary: Dictionary<Int, Character> = [:]
var ascii: [Int: Character] = [65: "A", 66: "B", 67: "C", 68: "D"]

ascii[65] = "a"	// 키 65인 것의 값을 "a"로 변경
ascii[69] = "E"	// 키 69로 "E"라는 값 추가

print(ascii)

💻 출력
[69: "E", 68: "D", 66: "B", 65: "a", 67: "C"]


✅ Dictionary Properties & Method

📖 isEmpty

배열과 마찬가지로 isEmpty 프로퍼티를 통해 배열이 비어있는지 아닌지 확인할 수 있다.
예제를 보면 다음과 같다.

📄 입력

import UIKit

var emptyDictionary: Dictionary<Int, Character> = [:]
var ascii: [Int: Character] = [65: "A", 66: "B", 67: "C", 68: "D"]

print(ascii.isEmpty)
print(emptyDictionary.isEmpty)

💻 출력

false
true

📖 count

배열과 마찬가지로 count 프로퍼티를 통해 배열에 몇개의 요소가 존재하는지 알 수 있다.
예제는 다음과 같다.

📄 입력

import UIKit

var emptyDictionary: Dictionary<Int, Character> = [:]
var ascii: [Int: Character] = [65: "A", 66: "B", 67: "C", 68: "D"]

print(ascii.count)
print(emptyDictionary.count)

💻 출력

4
0

📖 removeValue(forKey:)

값을 지울때는 removeValue(forKey:)메서드를 사용한다.
배열의 remove(_:)메서드와 마찬가지로 키에 해당하는 값이 제거된 후 반환된다.

📄 입력

import UIKit

var emptyDictionary: Dictionary<Int, Character> = [:]
var ascii: [Int: Character] = [65: "A", 66: "B", 67: "C", 68: "D"]

ascii.removeValue(forKey: 65)

print(ascii)

💻 출력
[68: "D", 67: "C", 66: "B"]

✅ Array vs. Dictionary

배열은 내부에 값이 없으면 오류가 발생한다.
예를 들어, 길이가 5(index0~4)인 배열에서 내가 6번째 요소(index5인 요소)를 꺼내려하면 오류가 난다.

반면에 딕셔너리의 경우, 내부에 없는 키로 접근해도 오류가 나지 않고 nil을 반환한다.
그리고 키에 해당하는 값이 없는 경우 default 값을 설정하여 반환할 수도 있다.
아래는 이에 대한 딕셔너리 예제이다.

📄 입력

import UIKit

var emptyDictionary: Dictionary<Int, Character> = [:]
var ascii: [Int: Character] = [65: "A", 66: "B", 67: "C", 68: "D"]

ascii.removeValue(forKey: 65)	// 키 65에 해당하는 값 삭제

print(ascii[65])	// 키 65에 해당하는 값이 존재하지 않음 (nil)
print(ascii[65, default: "?"])	// 키 65에 해당하는 값이 없으면 기본값 "?"반환

💻 출력

nil
?

✅ Set

Set는 같은 타입의 데이터를 순서 없이 하나의 묶음으로 저장하는 형태의 컬렉션 타입이다.
보통 순서가 중요하지 않거나, 각 요소가 유일한 값이어야 하는 경우 사용한다.
또한, 세트의 요소로는 해시 가능한 값이 들어와야 한다.
(-> Swift 표준 라이브러리의 Hashable 프로토콜을 따른다는 것을 의미)
세트를 선언하는 방법은 아래와 같이 Set<datatype> 이다.
세트의 경우 축약형이 없다.

// String 타입의 people Set 선언
var people: Set<String> = ["Vina","Mei","Hoho","Coco"]
//String 타입의 비어있는 Set 선언
var emptySet: Set<String> = []

Array와 매우 유사하게 선언하는 것을 볼 수 있다.
따라서 아래와 같이 선언하게 되는 경우 세트가 아닌 Array로 선언된다.

var people = ["Vina","Mei","Hoho","Coco"] // => Array인 people이 생성

✅ Set Properties & Method

📖 isEmpty

배열이나 딕셔너리와 마찬가지로 isEmpty 프로퍼티를 통해 배열이 비어있는지 아닌지 확인할 수 있다.
예제를 보면 다음과 같다.
📄 입력

import UIKit

var people: Set<String> = ["Vina","Mei","Hoho","Coco"]
var emptySet: Set<String> = []

print(people.isEmpty)
print(emptySet.isEmpty)

💻 출력

false
true

📖 insert(_:), remove(_:)

세트의 경우 순서가 없다.
따라서 append가 있지 않고 그냥 insert로 추가하면 된다.

insert(_:) : 세트에 요소 추가
remove(_:) : 세트의 요소 삭제 후 반환

✨ insert(_:) 예제

import UIKit

var people: Set<String> = ["Vina","Mei","Hoho","Coco"]
people.insert("Momo")

// =>["Coco", "Hoho", "Vina", "Momo", "Mei"]

✨ remove(_:) 예제

import UIKit

var people: Set<String> = ["Vina","Mei","Hoho","Coco"]
people.remove("Hoho")

// =>["Mei", "Coco", "Vina"]

✅ Set의 집합연산

세트는 앞서 이야기한 것과 같이 각 요소의 값이 유일하다는 특징을 갖는다.
따라서 집합관계를 표현하는 경우 매우 쓰기 좋다.
아래와 같이 전체 인원과 컴퓨터 수업을 듣는 사람들의 세트와 영어 수업을 듣는 사람들의 세트가 있는 경우를 이야기해보자.

var allPeople: Set<String> = ["Vina","Mei","Hoho","Coco","Momo","Jojo","Popo","Toto"]

var computerClassPeople: Set<String> = ["Vina","Mei","Hoho","Coco"]
var englishClassPeople: Set<String> = ["Vina","Mei","Momo","Jojo"]

이 경우를 우리가 중학교때 배운 집합이라고 생각하고 그려보면 아래와 같다.

이제 여기서 컴퓨터 수업과 영어 수업을 듣는 사람들의 합집합, 교집합, 차집합, 여집합의 합을 생각해보자.

📖 합집합

컴퓨터 수업과 영어 수업을 듣는 사람들의 합집합은
["Vina","Mei","Hoho","Coco","Momo","Jojo"]이다.
이 경우 union()을 통해 아래와 같이 결과를 반환할 수 있다.

📄 입력

import UIKit

var allPeople: Set<String> = ["Vina","Mei","Hoho","Coco","Momo","Jojo","Popo","Toto"]
var computerClassPeople: Set<String> = ["Vina","Mei","Hoho","Coco"]
var englishClassPeople: Set<String> = ["Vina","Mei","Momo","Jojo"]

print(computerClassPeople.union(englishClassPeople))

💻 출력
["Mei", "Hoho", "Coco", "Jojo", "Momo", "Vina"]

📖 교집합

컴퓨터 수업과 영어 수업을 듣는 사람들의 교집합은
["Vina","Mei"]이다.
이 경우 intersection()을 통해 아래와 같이 결과를 반환할 수 있다.

📄 입력

import UIKit

var allPeople: Set<String> = ["Vina","Mei","Hoho","Coco","Momo","Jojo","Popo","Toto"]
var computerClassPeople: Set<String> = ["Vina","Mei","Hoho","Coco"]
var englishClassPeople: Set<String> = ["Vina","Mei","Momo","Jojo"]

print(computerClassPeople.intersection(englishClassPeople))

💻 출력
["Mei", "Vina"]

📖 차집합

컴퓨터 수업에서 영어 수업을 듣는 사람들의 차집합은
["Coco", "Hoho"]이다.
이 경우 intersection()을 통해 아래와 같이 결과를 반환할 수 있다.

📄 입력

import UIKit

var allPeople: Set<String> = ["Vina","Mei","Hoho","Coco","Momo","Jojo","Popo","Toto"]
var computerClassPeople: Set<String> = ["Vina","Mei","Hoho","Coco"]
var englishClassPeople: Set<String> = ["Vina","Mei","Momo","Jojo"]

print(computerClassPeople.subtracting(englishClassPeople))

💻 출력
["Coco", "Hoho"]

📖 여집합의 합 (배타적 논리합)

컴퓨터 수업과 영어 수업을 듣는 사람들의 두 집합의 여집합의 합은
["Coco", "Jojo", "Hoho", "Momo"]이다.
이 경우 symmetricDifference()을 통해 아래와 같이 결과를 반환할 수 있다.

📄 입력

import UIKit

var allPeople: Set<String> = ["Vina","Mei","Hoho","Coco","Momo","Jojo","Popo","Toto"]
var computerClassPeople: Set<String> = ["Vina","Mei","Hoho","Coco"]
var englishClassPeople: Set<String> = ["Vina","Mei","Momo","Jojo"]

print(computerClassPeople.symmetricDifference(englishClassPeople))

💻 출력
["Coco", "Jojo", "Hoho", "Momo"]

📖 포함관계 연산

그 이외에도 세트에 다음과 같은 메서드를 이용하면 포함관계 연산이 가능하다.

메서드사용
A.isDisjoint(with: B)서로 배타적인지 확인
A.isSubset(of: B)A가 B의 부분집합인지 확인
A.isSuperset(of: B)A가 B의 전체집합인지 확인

✨ Collection 임의의 요소 추출 및 뒤섞기

Swift 4.2 버전부터 아래 두 메서드가 추가되었다.

메서드사용
ARRAY.randomElement()배열의 임의의 요소 반환
ARRAY.suffled()뒤죽박죽 배열로 반환
Set.suffled()세트를 섞으면 배열로 반환
DICTIONARY.suffled()딕셔너리 섞으면 (키,값)이 쌍을 이룬 튜플 배열로 반환
String.suffled()String도 컬렉션이다 (놀랍게도)



📌 마무리

튜플이나 딕셔너리나 세트나,, 잘 모르는 개념이지만 정리하고 보니 개념이 확실해진다.
기본적인 개념인데 내가 이렇게 정리하고 뿌듯해하다니,, 그동안 얼마나 공부를 안한거지,,
근데 생각보다 양이 진짜 많다.(정리도 꽤 오래 걸린다.)
이번주 중에 내가 공부 중인 책의 12강까지 정리해보자는 계획을 벌써 못지킬거같다.
뭐 그래도 할 수 있는 만큼 해보자.
항상 아자아자 마인드 잊지말기. 💪✨



참고
- 야곰, 『스위프트 프로그래밍 3판』, 한빛미디어, 2021.04
- the swift programming language swift 5.7
- Swift | Apple Developer Documentation
profile
아자아자 코딩라이푸 ٩(๑❛ʚ❛๑)۶

0개의 댓글