튜플 (Tuple)
- 튜플은 여러 개의 값을 한 묶음으로 만드는 Compound(복합 / 혼합) 타입
- 특별하게 타입이 정해져 있지 않다
- 포함될 데이터의 갯수를 마음대로 정의할 수 있다
("Royce", 20, "서울")
(Int, Int)
(Int, Int, Int)
- 사용하는 이유:
- 관련 데이터 그룹화: 서로 관련 있는 여러 데이터를 하나로 묶어 관리하면, 코드가 더 깔끔해지고 관련 데이터를 한눈에 보기 쉬워진다
- 간편한 전달: 함수를 호출할 때 여러 개의 값을 한 번에 반환하거나 전달할 때 유용하다
- 임시 데이터 저장: 간단하게 여러 값을 임시로 저장하고 사용할 때 좋다
let person = ("Royce", 20)
print("이름: \(person.0)")
print("나이: \(person.1)")
Named Tuple
- 일반 튜플은 여러 값을 순서대로 저장하지만, 인덱스로 값을 접근해야 한다
- 하지만 Named Tuple은 각 요소에 이름을 부여하여, 해당 이름을 통해 값에 접근할 수 있다
- Named Tuple을 사용하는 이유:
- 가독성 향상: 각 요소에 의미 있는 이름을 부여함으로써, 코드 내에서 해당 값이 무엇을 나타내는지 바로 알 수 있다
- 유지보수 용이: 인덱스 대신 이름으로 값을 참조하기 때문에, 튜플의 순서가 바뀌거나 요소가 추가되더라도 코드의 의도를 명확하게 유지할 수 있다
- 함수 반환값으로 유용: 여러 값을 한 번에 반환할 때, 각각의 반환값에 이름을 부여하면, 함수를 호출하는 쪽에서 어떤 값이 무엇인지 쉽게 파악할 수 있다
let person1 = ("Royce", 20)
print("이름: \(person1.0), 나이: \(person1.1)")
let person2 = (name: "Royce", age: 20)
print("이름: \(person2.name), 나이: \(person2.age)")
튜플의 분해(Decomposition)
- 튜플의 분해는 하나의 튜플에 담긴 값들을 각각의 변수나 상수에 한 번에 할당하는 과정이다
- 예를 들어,
(name: "Royce", age: 20)과 같은 튜플이 있을 때, 이 튜플을 분해하여 name과 age라는 별도의 변수에 담을 수 있다
- 사용하는 이유:
- 가독성 향상: 튜플의 각 요소에 대해 직접 변수 이름을 부여할 수 있어, 어떤 값이 무엇을 의미하는지 쉽게 알 수 있다
- 코드의 간결함: 인덱스로 접근할 필요 없이, 각 요소에 이름으로 접근할 수 있으므로 코드가 단순해진다
- 유지보수 용이: 데이터의 의미가 명확하게 표현되기 때문에, 나중에 코드를 수정하거나 확장할 때 이해하기 쉽다
let (first, second, third) = (1, 2, 3)
let person = ("Royce", 20)
let (name, age) = person
print("이름: \(name)")
print("나이: \(age)")
let personInfo = ("Royce", 20, "Developer")
let (name, age, _) = personInfo
print("이름: \(name), 나이: \(age)")
typealias GridPoint = (Int, Int)
튜플의 값 비교 (실제로 사용하는 경우는 흔치 않음)
- 튜플 값의 비교는 두 개의 튜플에 담긴 값들을 순서대로 하나씩 비교하여(사전식(lexicographical) 비교), 전체 튜플 간의 순서를 결정하는 것을 의미한다
- Swift에서는 튜플의 모든 요소가 비교 가능한(Comparable) 타입일 경우, 튜플끼리 직접 비교할 수 있다
- 튜플의 각 요소가 모두 Comparable 프로토콜을 준수해야 한다
- 즉, 각 요소가 <, <=, >, >=, == 등의 연산자를 사용할 수 있어야 튜플 전체에 대한 비교가 가능하다
- 튜플 값을 비교하는 이유
- 정렬 및 순서 결정: 여러 개의 값을 함께 저장한 튜플을 정렬할 때, 튜플 값의 비교를 통해 쉽게 순서를 결정할 수 있다(예: 학생 점수와 이름을 담은 튜플 배열을 점수 순으로 정렬)
- 코드 간결성: 각각의 요소를 일일이 비교하는 대신, 튜플 전체를 한 번에 비교할 수 있어 코드가 훨씬 간단해진다
- 가독성 향상: 튜플 자체에 의미 있는 순서가 있다면, 비교 연산자를 통해 그 순서를 바로 파악할 수 있으므로 코드의 의도가 명확해진다
let tuple1 = (1, "apple")
let tuple2 = (1, "banana")
if tuple1 < tuple2 {
print("tuple1이 tuple2보다 작습니다.")
} else {
print("tuple1이 tuple2보다 크거나 같습니다.")
}
var students = [
(name: "Alice", score: 85),
(name: "Bob", score: 92),
(name: "Charlie", score: 85)
]
let sortedStudents = students.sorted {
return ($0.score, $0.name) < ($1.score, $1.name)
}
for student in sortedStudents {
print("\(student.name): \(student.score)")
}
Tuple과 switch 문
튜플의 매칭(Matching)
let iOS = (language: "Swift", version: "5")
if iOS.0 == "Swift" && iOS.1 = "5" {
print("스위프트 버전 5 입니다.")
}
if iOS == ("Swift", "5") {
print("스위프트 버전 5 입니다.")
}
switch iOS {
case ("Swift", "5"):
print("스위프트 버전 5 입니다.")
default:
break
}
튜플의 활용
let coordinate = (x: 3, y: 0)
switch coordinate {
case (0, 0):
print("좌표가 원점입니다.")
case (let x, 0):
print("x축 위에 위치합니다. x = \(x)")
case (0, let y):
print("y축 위에 위치합니다. y = \(y)")
case let (x, y) where x == y:
print("x와 y의 값이 같고, x = y 1차 함수의 그래프 위에 있습니다. 좌표 = (\(x), \(y))")
case let (x, y) where x == -y:
print("x와 y의 값이 같고, x = -y 1차 함수의 그래프 위에 있습니다. 좌표 = (\(x), \(y))")
default:
print("일반적인 위치입니다. 좌표 = (\(coordinate.x), \(coordinate.y))")
}