TIL: 컬렉션(Collection)

Royce·2025년 3월 16일

Swift 문법

목록 보기
20/63

컬렉션(Collection)

Swift의 컬렉션(Collection)은 여러 개의 값을 저장하고 관리하는 데이터 구조이다
컬렉션에는 배열(Array), 딕셔너리(Dictionary), 집합(Set) 세 가지 주요 유형이 있다

  • Swift의 컬렉션은 다음과 같은 특성을 가진다
    • 값을 여러 개 저장할 수 있다
    • 값의 순서가 있는지 여부에 따라 분류된다
    • 값을 중복 허용하는지 여부에 따라 분류된다
    • 컬렉션은 Array, Dictionary, Set 세 가지 주요 유형이 있다
컬렉션 타입순서 유지중복 허용설명
Array✅ 유지✅ 허용순서가 있는 값들의 리스트
Dictionary❌ 유지 안 함키 중복 불가키-값(Key-Value) 쌍으로 데이터 저장
Set❌ 유지 안 함허용 안 함중복 없는 고유한 값들의 집합

배열(Array)

  • 배열(Array)은 같은 타입의 값들을 순서대로 저장하는 컬렉션 타입이다
  • 값은 인덱스(Index, 0부터 시작)를 이용하여 접근할 수 있다

배열 선언 방법

  • Swift에서 배열을 선언하는 방법은 여러 가지가 있다

리터럴(Literal)로 배열 선언

var names = ["Royce", "Steve", "Alice", "Bob", "Charlie"] // ✅ String 타입의 배열
var numbers = [1, 2, 3, 4, 5] // ✅ Int 타입의 배열

명시적으로 타입을 지정하여 배열 선언

var names: [String] = ["Royce", "Steve", "Alice", "Bob", "Charlie"]
var numbers: [Int] = [1, 2, 3, 4, 5]
  • 배열 타입을 명확하게 지정할 수 있다([String], [Int])

빈 배열 선언

var emptyArray1: [String] = [] // ✅ 빈 배열 (String 타입)
var emptyArray2 = [Int]() // ✅ 빈 배열 (Int 타입)
var emptyArray3: Array<Double> = Array() // ✅ 빈 배열 (Double 타입)
  • 빈 배열을 생성할 때 [] 또는 Array<T>()를 사용 가능

기본값을 가지는 배열 생성

var fiveSteves = Array(repeating: "Steve", count: 5) // ✅ ["Steve", "Steve", "Steve", "Steve", "Steve"]
var fiveRoyces = [String](repeating: "Royce", count: 5) // ✅ ["Royce", "Royce", "Royce", "Royce", "Royce"]
  • Array(repeating:count:)를 사용하여 특정 값이 반복되는 배열 생성 가능

배열(Array) 요소(Element) 접근

배열 요소 접근 방법

  • 배열의 요소에 접근하려면 인덱스(Index)를 사용한다
  • 인덱스는 0부터 시작하며, 배열의 크기 -1 까지 존재한다
let names = ["Royce", "Steve", "Alice", "Bob", "Charlie"]

print(names[0]) // ✅ "Royce"
print(names[1]) // ✅ "Steve"
print(names[2]) // ✅ "Alice"

배열에서 첫 번째 요소(.first)와 마지막 요소(.last) 가져오기

let names = ["Royce", "Steve", "Alice", "Bob", "Charlie"]

print(names.first ?? "No Name") // ✅ "Royce"
print(names.last ?? "No Name")  // ✅ "Charlie"
  • 배열이 비어있을 경우 nil을 반환하므로 ?? 연산자로 기본값 설정 가능

배열에서 특정 요소의 첫 번째와 마지막 인덱스 찾기

  1. firstIndex(of:) ➡️ 첫 번째 인덱스 찾기
let names = ["Alice", "Royce", "Steve", "Royce", "Bob"]

if let index = names.firstIndex(of: "Royce") {
    print("첫 번째 'Royce'의 위치: \(index)") // ✅ 1
} else {
    print("'Royce'가 없습니다.")
}
  1. lastIndex(of:) ➡️ 마지막 인덱스 찾기
if let index = names.lastIndex(of: "Royce") {
    print("마지막 'Royce'의 위치: \(index)") // ✅ 3
} else {
    print("'Royce'가 없습니다.")
}
  • 중복된 요소가 있으 경우 firstIndex(of:)는 첫 번째, lastIndex(of:)는 마지막 요소의 인덱스를 반환

배열의 인덱스 확인(.startIndex, .endIndex)

let names = ["Royce", "Steve", "Alice", "Bob", "Charlie"]

print(names.startIndex) // ✅ 0 (배열의 시작 인덱스)
print(names.endIndex)   // ✅ 5 (마지막 인덱스 +1 값)
  • startIndex는 항상 0, endIndex는 마지막 인덱스보다 1 큰 값

배열(Array)의 요소 변경(Element Modification)

변경 방법메서드 또는 연산자설명
단일 요소 변경[index] = newValue특정 위치의 요소 변경
범위 내 여러 요소 변경replaceSubrange(_:with:)여러 요소를 한 번에 변경
첫 번째 요소 변경.first배열의 첫 번째 요소 변경
마지막 요소 변경.last배열의 마지막 요소 변경
특정 값의 위치 찾아 변경firstIndex(of:), lastIndex(of:)특정 값이 있는 위치를 찾아 변경
모든 요소 변경indices / map배열의 모든 요소 변경
요소 추가append(_:)배열의 끝에 요소 추가
요소 삽입insert(_:at:)특정 위치에 요소 추가
요소 삭제remove(at:), removeFirst(), removeLast(), removeAll()특정 요소 또는 전체 삭제
요소 정렬.sort(), .sorted()배열 요소 정렬(원본 변경 또는 새 배열 반환)
요소 반전.reverse(), .reversed()배열 요소 순서 반전(원본 변경 또는 새 배열 반환)
요소 섞기.suffle(), .shuffled()배열 요소 무작위 섞기(원본 변경 또는 새 배열 반환)
배열 비교==, !=, elementsEqual(_:)두 배열이 같은지 비교
배열 활용joined(), reduce(), filter(), map(), contains()배열을 변형하거나 활용하는 다양한 방법
인덱스와 값 동시에 활용.enumerated()배열의 인덱스와 값을 동시에 가져오기

배열 요소 변경

특정 위치의 요소 변경([index] = value)

  • 배열의 특정 인덱스에 있는 요소를 변경하려면 [index] = value 문법을 사용한다
var names = ["Royce", "Steve", "Alice", "Bob", "Charlie"]

names[2] = "Eve" // 2번 인덱스("Alice")를 "Eve"로 변경

print(names) // ✅ ["Royce", "Steve", "Eve", "Bob", "Charlie"]

특정 범위의 요소 변경 (replaceSubrange)

var names = ["Royce", "Steve", "Alice", "Bob", "Charlie"]

names.replaceSubrange(1...2, with: ["Eve", "David"]) // 1~2번 요소 변경

print(names) // ✅ ["Royce", "Eve", "David", "Bob", "Charlie"]

배열 요소 추가

배열 끝에 요소 추가 (append(_:))

var names = ["Royce", "Steve"]

names.append("Alice") // 배열 끝에 "Alice" 추가

print(names) // ✅ ["Royce", "Steve", "Alice"]

특정 위치에 요소 추가(insert(_:at:))

var names = ["Royce", "Steve", "Alice"]

names.insert("Charlie", at: 1) // 1번 인덱스에 "Charlie" 삽입

print(names) // ✅ ["Royce", "Charlie", "Steve", "Alice"]

배열 요소 삭제

특정 위치의 요소 삭제(remove(at:))

var names = ["Royce", "Steve", "Alice", "Bob", "Charlie"]

names.remove(at: 2) // 2번 인덱스("Alice") 삭제

print(names) // ✅ ["Royce", "Steve", "Bob", "Charlie"]

모든 요소 삭제(removeAll())

var names = ["Royce", "Steve", "Alice"]

names.removeAll()

print(names) // ✅ []

배열 요소 정렬(.sort() vs .sorted())

정렬 방법동작 방식원본 변경 여부
.sort()배열을 정렬된 상태로 변경✅ 원본 변경
sorted()정렬된 새 배열을 반환❌ 원본 변경 없음

원본을 직접 정렬(.sort())

var numbers = [5, 2, 8, 3, 1]

numbers.sort() // 오름차순 정렬

print(numbers) // ✅ [1, 2, 3, 5, 8]

정렬된 새 배열 반환(.sorted())

let numbers = [5, 2, 8, 3, 1]

let sortedNumbers = numbers.sorted() // 새로운 정렬된 배열 생성

print(sortedNumbers) // ✅ [1, 2, 3, 5, 8]
print(numbers) // ✅ [5, 2, 8, 3, 1] (원본 유지)

배열 요소 반전 (.reverse() vs .reversed())

반전 방법동작 방식원본 변경 여부
.reverse()배열을 반전된 상태로 변경✅ 원본 변경
.reversed()반전된 새 배열을 반환❌ 원본 변경 없음

원본을 직접 반전(.reverse())

var numbers = [1, 2, 3, 4, 5]

numbers.reverse() // 원본 배열 반전

print(numbers) // ✅ [5, 4, 3, 2, 1]

반전된 새 배열 반환(.reversed())

let numbers = [1, 2, 3, 4, 5]

let reversedNumbers = numbers.reversed() // 새로운 반전된 배열 생성

print(Array(reversedNumbers)) // ✅ [5, 4, 3, 2, 1]

배열 요소 무작위 섞기(.shuffle(), .shuffled())

| 섞기 방법 | 동작 방식 | 원본 변경 여부 |
| .shuffle() | 배열을 무작위 순서로 변경 | ✅ 원본 변경 |
| .shuffled() | 무작위로 섞인 새 배열을 반환 | ❌ 원본 변경 없음 |


원본을 직접 섞기(.shuffle())

var numbers = [1, 2, 3, 4, 5]

numbers.shuffle() // 배열 요소 무작위 섞기

print(numbers) // ✅ 예: [3, 5, 1, 4, 2] (랜덤 결과)

무작위로 섞인 새 배열 반환(.shuffled())

let numbers = [1, 2, 3, 4, 5]

let shuffledNumbers = numbers.shuffled() // 새로운 무작위 배열 생성

print(shuffledNumbers) // ✅ 예: [4, 1, 5, 2, 3] (랜덤 결과)
print(numbers) // ✅ [1, 2, 3, 4, 5] (원본 유지)

배열 요소 비교

배열이 같은지 비교(==, !=)

let array1 = [1, 2, 3, 4, 5]
let array2 = [1, 2, 3, 4, 5]
let array3 = [1, 2, 3, 4]

print(array1 == array2) // ✅ true (두 배열이 동일함)
print(array1 == array3) // ✅ false (배열의 길이가 다름)
print(array1 != array3) // ✅ true (배열이 다름)
  • 배열이 같은지 비교할 때는 == 연산자를 사용한다

배열 요소 순서까지 동일한지 비교(elementsEqual(_:))

let names1 = ["Royce", "Steve", "Alice"]
let names2 = ["Royce", "Steve", "Alice"]
let names3 = ["Alice", "Royce", "Steve"]

print(names1.elementsEqual(names2)) // ✅ true
print(names1.elementsEqual(names3)) // ✅ false (순서가 다름)
  • 배열의 모든 요소가 같은지 비교할 때 elementsEqual(_:)을 사용한다

특정 요소 포함 여부 확인(contains(_:))

let numbers = [10, 20, 30, 40, 50]

print(numbers.contains(30)) // ✅ true
print(numbers.contains(100)) // ✅ false
  • 배열에 특정 요소가 포함되어 있는지 확인할 때 contains(_:)를 사용한다

배열 활용

배열을 문자열로 변환(joined())

let words = ["Swift", "is", "awesome"]

let sentence = words.joined(separator: " ")
print(sentence) // ✅ "Swift is awesome"
  • 배열의 요소를 문자열로 변환할 때 joined(separator:)를 사용한다

배열의 요소를 합산(reduce(_:_:))

let numbers = [1, 2, 3, 4, 5]

let sum = numbers.reduce(0, +) // ✅ 모든 요소를 합산
print(sum) // ✅ 15

-reduce를 사용하면 배열의 요소를 누적하여 계산 가능하다


배열에 특정 요소만 필터링(filter(_:))

let numbers = [10, 20, 30, 40, 50]

let filtered = numbers.filter { $0 > 25 }
print(filtered) // ✅ [30, 40, 50]
  • filter(_:)를 사용하면 특정 조건을 만족하는 요소만 선택

배열 요소를 변형(map(_:))

let numbers = [1, 2, 3, 4, 5]

let doubled = numbers.map { $0 * 2 }
print(doubled) // ✅ [2, 4, 6, 8, 10]
  • map(_:)을 사용하면 배열의 각 요소를 변형하여 새로운 배열을 생성 가능

배열의 인덱스와 값 동시에 활용하기(.enumerated())

  • 배열을 순회하면서 인덱스와 요소 값을 동시에 가져올 때 enumerated() 메서드를 사용한다

enumerated() 기본 사용법

let names = ["Royce", "Steve", "Alice", "Bob"]

for (index, name) in names.enumerated() {
    print("\(index): \(name)")
}


// 출력 결과
0: Royce
1: Steve
2: Alice
3: Bob
  • 배열의 인덱스(index)와 요소 값(name)을 동시에 가져올 수 있다

enumerated()를 활용한 요소 변경

  • 배열을 순회하면서 특정 요소를 변경할 수도 있다
// 각 요소를 2배로 변경하면서 배열을 업데이트 한다
var numbers = [10, 20, 30, 40, 50]

for (index, value) in numbers.enumerated() {
    numbers[index] = value * 2
}

print(numbers) // ✅ [20, 40, 60, 80, 100]

짝수 인덱스만 출력

// 짝수 인덱스(0, 2, 4)만 선택적으로 출력
let numbers = [5, 10, 15, 20, 25]

for (index, value) in numbers.enumerated() {
    if index % 2 == 0 {
        print("짝수 인덱스 \(index)의 값: \(value)")
    }
}


// 출력 결과
짝수 인덱스 0의 값: 5
짝수 인덱스 2의 값: 15
짝수 인덱스 4의 값: 25

enumerated()filter() 함께 사용

  • 배열에 특정 조건을 만족하는 요소만 선택하고 싶을 때 enumerated()filter()를 함께 사용할 수 있다
// 짝수 인덱스의 요소만 선택하여 배열로 변환
let numbers = [10, 21, 32, 43, 54]

let evenIndexNumbers = numbers.enumerated().filter { index, _ in index % 2 == 0 }

print(evenIndexNumbers) // ✅ [(0, 10), (2, 32), (4, 54)]

enumerated()map() 함께 사용

  • map()을 사용하면 기존 배열을 변환하면서 인덱스 값을 함께 사용할 수 있다
// 각 요소를 "index x: value" 형식의 문자로 변환하여 새로운 배열 생성
let numbers = [10, 20, 30, 40]

let indexedNumbers = numbers.enumerated().map { index, value in
    "Index \(index): \(value)"
}

print(indexedNumbers)
// ✅ ["Index 0: 10", "Index 1: 20", "Index 2: 30", "Index 3: 40"]

딕셔너리(Dictionary)

  • 딕셔너리는 각 키(Key)마다 하나의 값(Value)을 저장하는 키-값(Key-Value) 기반의 컬렉션이다
  • 배열(Array)과 달리 순서(Order)가 없으며, 키(Key)를 이용하여 빠르게 값을 찾을 수 있다

딕셔너리의 특징

  • 키(Key)는 고유(unique)해야 한다(중복 불가능)
  • 값(Value)은 중복 가능
  • 키(Key)는 Hashable 타입이어야 한다
  • 검색, 추가, 삭제가 매우 빠르다(Hash Table 구조 사용)

딕셔너리의 정식 문법과 단축 문법

정식 문법(Full Syntax)

// Dictionary<Key, Value> 형태로 선언하며, 타입을 명시적으로 지정한다
var students: Dictionary<String, Int> = Dictionary<String, Int>()

// 딕셔너리를 직접 초기화할 수도 있다
var students: Dictionary<String, Int> = ["Royce": 90, "Steve": 85, "Alice": 95]

단축 문법(Shorthand Syntax)

// Dictionary<Key, Value> 대신 [Key: Value] 형식을 사용하여 간결하게 표현
var students: [String: Int] = [:]

// 타입 추론을 활용하여 [Key: Value] 형식만 사용해도 자동으로 딕셔너리로 인식된다
var students = ["Royce": 90, "Steve": 85, "Alice": 95]

딕셔너리의 주요 기능

요소 접근([] 서브스크립트)

// 키(Key)가 존재하면 해당 값(Value)을 반환, 없으면 nil을 반환
print(students["Royce"]) // ✅ Optional(90)
print(students["Bob"])    // ✅ nil (존재하지 않는 키)

값 변경 및 추가 ([] 사용)

// 기존 키의 값을 변경하거나, 존재하지 않는 키를 추가할 수도 있다
students["Steve"] = 88 // 기존 값 변경
students["Charlie"] = 80 // 새로운 키-값 추가

print(students) // ✅ ["Royce": 90, "Steve": 88, "Alice": 95, "Charlie": 80]

특정 키 제거 (removeValue(forKey:))

// 키를 삭제하면 해당 값도 제거된다
students.removeValue(forKey: "Steve") // "Steve" 삭제
print(students) // ✅ ["Royce": 90, "Alice": 95, "Charlie": 80]

특정 키 존재 여부 확인 (contains)

//딕셔너리의 특정 키가 존재하는지 확인 가능
print(students.keys.contains("Royce")) // ✅ true
print(students.keys.contains("Bob"))   // ✅ false

기본값을 제공하는 접근 (default:)

// 키가 존재하지 않을 때 기본값을 설정 가능
let royceScore = students["Royce", default: 0] // ✅ 90
let bobScore = students["Bob", default: 0]    // ✅ 0

모든 키/값 조회

// .keys는 모든 키를, .values는 모든 값을 배열로 반환
print(students.keys)   // ✅ ["Royce", "Alice", "Charlie"]
print(students.values) // ✅ [90, 95, 80]

딕셔너리 크기 확인 (.count)

// 딕셔너리에 저장된 키-값 쌍의 개수를 반환
print(students.count) // ✅ 3

딕셔너리가 비어 있는지 확인 (.isEmpty)

// 딕셔너리에 요소가 하나도 없는지 확인
print(students.isEmpty) // ✅ false

랜덤 요소 가져오기 (.randomElement())

// 딕셔너리에서 랜덤한 키-값 쌍을 반환 (없으면 nil 반환)
if let randomStudent = students.randomElement() {
    print(randomStudent)
}

딕셔너리 정렬 (sorted())

// 딕셔너리는 정렬되지 않은 컬렉션이므로, sorted()를 사용하여 새로운 배열을 반환함
let sortedByKey = students.sorted { $0.key < $1.key }
print(sortedByKey) // ✅ 키를 기준으로 정렬

let sortedByValue = students.sorted { $0.value < $1.value }
print(sortedByValue) // ✅ 값을 기준으로 정렬

딕셔너리 값 업데이트 (updateValue(forKey:))

// 기존 값을 변경하며, 기존에 값이 없으면 nil을 반환
students.updateValue(92, forKey: "Alice")
print(students) // ✅ ["Royce": 90, "Steve": 85, "Alice": 92]

딕셔너리 비교

  • 딕셔너리의 동등성 비교(==, !=)
// 두 딕셔너리가 같으려면 키(Key)와 값(Value) 모두 동일해야 한다
let dict1 = ["Royce": 90, "Steve": 85, "Alice": 95]
let dict2 = ["Royce": 90, "Steve": 85, "Alice": 95]
let dict3 = ["Royce": 90, "Steve": 80, "Alice": 95]

print(dict1 == dict2) // ✅ true (같은 키-값)
print(dict1 == dict3) // ✅ false (값이 다름)
print(dict1 != dict3) // ✅ true (다른 딕셔너리)
  • 특정 키 또는 값 비교
// .keys와 .values를 사용하여 각각 비교할 수 있다
print(dict1.keys == dict2.keys)   // ✅ true (같은 키)
print(dict1.values == dict2.values) // ✅ true (같은 값)
print(dict1.keys == dict3.keys)   // ✅ true (키는 동일)
print(dict1.values == dict3.values) // ✅ false (값이 다름)

딕셔너리의 중첩 사용(Nested Dictionary)

  • 중첩 딕셔너리 선언
// 각 학생이 여러 과목의 점수를 저장하는 구조
var students: [String: [String: Int]] = [
    "Royce": ["Math": 90, "Science": 85],
    "Steve": ["Math": 80, "Science": 88]
]
  • 중첩된 값에 접근
// 안전한 옵셔널 체이닝(?)을 사용하여 내부 값을 가져올 수 있다
print(students["Royce"]?["Math"]) // ✅ Optional(90)
print(students["Steve"]?["Science"]) // ✅ Optional(88)
  • 중첩된 값 변경
// 내부 딕셔너리의 값을 직접 변경할 수 있다
students["Royce"]?["Math"] = 95
print(students["Royce"]?["Math"]) // ✅ Optional(95)
  • 중첩된 값 추가
// 새로운 키를 추가하면 새로운 딕셔너리가 할당된다
students["Alice"] = ["Math": 92, "Science": 90]
print(students)

딕셔너리와 반복문(Iteration)

  • 딕셔너리의 키-값을 반복문으로 조회
// 키와 값을 동시에 가져올 수 있다
let studentScores = ["Royce": 90, "Steve": 85, "Alice": 95]

for (name, score) in studentScores {
    print("\(name): \(score)")
}


// 출력 결과
Royce: 90
Steve: 85
Alice: 95
  • 딕셔너리의 키만 조회
//  .keys를 사용하여 키만 가져올 수 있다
for name in studentScores.keys {
    print(name)
}


// 출력 결과
Royce
Steve
Alice
  • 딕셔너리의 값만 조회
// .values를 사용하여 값만 가져올 수 있다
for score in studentScores.values {
    print(score)
}


// 출력 결과
90
85
95
  • enumerated()를 사용하여 키-값을 인덱스와 함께 조회
// enumerated()를 사용하면 키-값 쌍을 인덱스와 함께 가져올 수 있다
for (index, (name, score)) in studentScores.enumerated() {
    print("\(index): \(name) - \(score)")
}


// 출력 결과
0: Royce - 90
1: Steve - 85
2: Alice - 95
  • 중첩 딕셔너리 반복문 활용
// 이중 for-in 반복문을 사용하여 중첩된 데이터를 순회할 수 있다
for (student, subjects) in students {
    print("\(student)의 성적:")
    for (subject, score) in subjects {
        print("  \(subject): \(score)")
    }
}


// 출력 결과
Royce의 성적:
  Math: 95
  Science: 85
Steve의 성적:
  Math: 80
  Science: 88

딕셔너리와 배열의 검색 속도 차이

데이터 구조검색 방식시간 복잡도
배열(Array)모든 요소를 순차 검색O(n) (최악의 경우)
딕셔너리(Dictionary)해시 테이블을 이용한 검색O(1) (평균적으로)

딕셔너리에서 Hashable이 중요한 이유

// 해시(Hash)는 데이터를 특정 숫자로 변환하여 빠르게 검색할 수 있도록 도와준다
protocol Hashable : Equatable {
    func hash(into hasher: inout Hasher)
}

해시(Hash)와 값의 유일성 보장

// 같은 데이터를 가진 객체는 같은 해시 값을 가져야 한다
struct Person: Hashable {
    let name: String
    let age: Int

    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(age)
    }
}

집합(Set)

Set의 특징

  • 순서가 없다 ➡️ 배열(Array)과 달리 순서가 보장되지 않는다
  • 중복된 요소를 허용하지 않는다 ➡️ 같은 값이 여러 번 저장되지 않는다
  • 빠른 검색 및 추가 / 삭제 ➡️ 평균적으로 O(1) 시간 복잡도 (Hash Table 기반)

Set 선언 방법 (정식 문법 vs 단축 문법)

정식 문법 (Full Syntax)

// Set<Element> 형태로 선언하며, 타입을 명시적으로 지정해야 한다
var numbers: Set<Int> = Set<Int>()
print(numbers) // ✅ []

// Set([])을 사용하여 초기화할 수도 있다
var numbers: Set<Int> = Set([1, 2, 3, 3, 4, 5])
print(numbers) // ✅ [1, 2, 3, 4, 5] (중복 제거)

단축 문법 (Shorthand Syntax)

// 타입 추론을 활용하여 Set임을 자동으로 인식 (Set<Int>로 변환됨)
var numbers: Set = [1, 2, 3, 3, 4, 5]
print(numbers) // ✅ [1, 2, 3, 4, 5]

// 타입이 명확하다면 빈 배열([])을 사용하여 초기화 가능
var emptySet: Set<String> = [] // 빈 Set
print(emptySet) // ✅ []

Set의 주요 기능

요소 추가 (insert)

// 이미 존재하는 값을 추가해도 변화 없다
numbers.insert(6)
print(numbers) // ✅ [1, 2, 3, 4, 5, 6]

요소 삭제 (remove)

// 존재하지 않는 값을 삭제하려 해도 에러가 발생하지 않는다
numbers.remove(3)
print(numbers) // ✅ [1, 2, 4, 5, 6]

특정 요소 포함 여부 확인 (contains)

print(numbers.contains(2)) // ✅ true
print(numbers.contains(10)) // ✅ false

Set 크기 확인 (count)

print(numbers.count) // ✅ 5

Set이 비어 있는지 확인 (isEmpty)

print(numbers.isEmpty) // ✅ false

랜덤 요소 가져오기 (randomElement())

print(numbers.randomElement() ?? "No element") // ✅ 랜덤 값

Set의 업데이트 (Update)

update(_:)를 사용한 값 추가 및 업데이트

// update(_:)는 새로운 값을 추가하거나, 기존 값이 있으면 교체하지 않고 그대로 유지
var fruits: Set = ["Apple", "Banana", "Cherry"]

// 새로운 요소 추가
fruits.update(with: "Mango")
print(fruits) // ✅ ["Apple", "Banana", "Cherry", "Mango"]

// 기존 요소 업데이트 (동일한 값이므로 변경 없음)
fruits.update(with: "Banana")
print(fruits) // ✅ ["Apple", "Banana", "Cherry", "Mango"]

Set의 집합 연산

  • Swift의 Set은 집합 연산(Set Operator)을 지원하며, 일반 연산(union, intersection 등)과 form으로 시작하는 원본 변경 연산이 있다

두 개의 Set 간 연산

var setA: Set = [1, 2, 3, 4, 5]
var setB: Set = [3, 4, 5, 6, 7]

// 합집합 (union)
print(setA.union(setB)) // ✅ [1, 2, 3, 4, 5, 6, 7]

// 교집합 (intersection)
print(setA.intersection(setB)) // ✅ [3, 4, 5]

// 차집합 (subtracting)
print(setA.subtracting(setB)) // ✅ [1, 2] (setA에만 있는 요소)

// 대칭 차집합 (symmetricDifference)
print(setA.symmetricDifference(setB)) // ✅ [1, 2, 6, 7] (서로 다른 요소)

원본을 변경하는 form 연산

// form 연산을 사용하면 새로운 Set을 생성하는 대신 원본을 변경한다
var setA: Set = [1, 2, 3, 4, 5]
var setB: Set = [3, 4, 5, 6, 7]

// 합집합 후 원본 변경 (formUnion)
setA.formUnion(setB)
print(setA) // ✅ [1, 2, 3, 4, 5, 6, 7]

// 교집합 후 원본 변경 (formIntersection)
setA = [1, 2, 3, 4, 5]
setA.formIntersection(setB)
print(setA) // ✅ [3, 4, 5]

// 차집합 후 원본 변경 (formSubtracting)
setA = [1, 2, 3, 4, 5]
setA.formSubtracting(setB)
print(setA) // ✅ [1, 2]

// 대칭 차집합 후 원본 변경 (formSymmetricDifference)
setA = [1, 2, 3, 4, 5]
setA.formSymmetricDifference(setB)
print(setA) // ✅ [1, 2, 6, 7]

Set과 for-in 반복문

// Set은 순서가 없으므로, 출력 순서는 실행할 때마다 다를 수 있다
let numbers: Set = [1, 2, 3, 4, 5]

for num in numbers {
    print(num)
}


// 출력 결과 (순서는 랜덤)
1
3
5
2
4
profile
iOS 개발자 지망생

0개의 댓글