Swift - 집단 자료형

이한솔·2023년 7월 28일
0

Swift 문법 🍎

목록 보기
7/32

objective-C (Foundation Collection)

클래스, 참조타입, 객체만 저장가능, 타입 상관없이 저장 가능
(NSArray, NSDictionary, NSSet)

Swift Collection

구조체, 값타입, 객체와 값 저장가능, 하나의 타입만 저장가능
(Array, Dictionary, Set, Tuple)

💡Copy-on-write

값 타입은 값을 복사해서 사용하는데 collection을 사용할때마다 요소들이 복사되면 시간이 오래 걸리고 메모리도 낭비된다.
Swift에서는 컬렉션은 요소가 실제로 바뀔때만 복사되고, 접근만 할때는 복사본 없이 원본에 접근하도록 최적화된 방법을 사용한다.



Array

일련의 순서를 가지는 리스트 형식의 값을 저장하는 데에 사용되는 자료형
하나의 배열에는 같은 타입만 저장할 수 있다.

Index: 배열에 입력되는 아이템들의 각각의 순서
인덱스는 0부터 시작하며 아이템이 추가될 때마다 차례대로 1씩 증가한다.
인덱스에 연결된 아이템이 삭제 되면 다음 아이템들이 차례대로 앞으로 이동하면서 빈 인덱스를 채워넣는다.

// 빈 배열 만들기, 배열 초기화
var emptyArray = Array<String>()
var emptyArray2 = [String]()

// 배열 순회 탐색하기 
var cities = ["Seoul", "New York", "LA"]

for row in cities {
    let index = cities.firstIndex(of: row) // 배열의 인덱스를 확인하여 index 상수에 대입
    print("\(index!)번째 도시는 \(row)입니다")
}

// 출력값: 
// 0번째 도시는 Seoul입니다
// 1번째 도시는 New York입니다
// 2번째 도시는 LA입니다


// 배열 아이템 추가
var cities = ["Seoul"]

// index로 배열 아이템에 접근
print(cities[0]) // 출력값: Seoul

// append: 입력된 값을 배열의 맨 뒤에 추가한다.
cities.append("New York")
print(cities) // 출력값: ["Seoul", "New York"]

// insert(_:at:): 아이템을 배열의 맨 뒤가 아닌 원하는 위치에 직접 추가하고 싶을 때 사용한다. at: 뒤에 입력되는 정수값의 인덱스 위치에 추가된다. 
cities.insert("LA", at: 0)
print(cities) // 출력값: ["LA", "Seoul", "New York"]

// append(contentsOf:): 여러 개의 아이템을 배열의 맨 마지막에 한꺼번에 추가할 때 사용한다.
cities.append(contentsOf: ["Chicago", "Seattle"])
print(cities) // 출력값: ["LA", "Seoul", "New York", "Chicago, Seattle"]


// 범위 연산자를 이용해서 바꾸기
cities[0...1] = ["a", "b"]
print(cities) // 출력값: ["a", "b", "New York", "Chicago, Seattle"]


// 배열 요소 삭제
// 첫번째 아이템 삭제
cities.removeFirst()
print(cities) // 출력값: ["b", "New York", "Chicago", "Seattle"]

// 마지막 아이템 삭제
cities.removeLast()
print(cities) // 출력값: ["b", "New York", "Chicago"]

// 1번째 인덱스 아이템 삭제
cities.remove(at: 1)
print(cities) // 출력값: ["b", "Chicago"]

// 모두 삭제
cities.removeAll()
print(cities) // 출력값: []


// 배열 요소 개수 확인
// count: 아이템 개수 return
print(cities.count) // 출력값: 0 

// isEmpty: 빈 배열인지 확인해서 bool값 return
cities.append("NewYork")
print(cities.isEmpty) // 출력값: false

// contains: 해당 아이템이 존재하는지 확인해서 bool값 return
print(cities.contains("s")) // 출력값: false
print(cities.contains("NewYork")) // 출력값: true


Dictionary

Key와 Value로 데이터를 저장하는 자료형
인덱스 대신 고유 키를 사용하여 값을 얻는다.
딕셔너리는 없는 키를 호출할 가능성이 있어서 키를 호출해서 저장된 값을 불러올 때나 업데이트 메서드를 실행한 결과를 Optional 타입으로 반환한다.

  1. 하나의 키는 하나의 데이터에만 연결되어야한다.
  2. 하나의 딕셔너리에서 키는 중복될 수 없다. 중복해서 선언하면 기존 키에 연결된 데이터가 수정된다.
  3. 저장할 수 있는 데이터 타입에는 제한이 없지만, 하나의 딕셔너리에 저장하는 데이터 타입은 모두 일치해야 한다.
  4. 딕셔너리의 아이템에는 순서가 없지만 키에는 내부적으로 순서가 있으므로 for~in 구문을 시용한 순회탐색이 가능하다.
  5. 딕셔너리에서 사용할 수 있는 키의 타입은 거의 제한이 없으나 해시(Hash) 연산이 가능한 타입이어야한다.
// 빈 dictionary 만들기, 초기화 key: Value
var emptyDictionary = [String: Int]()

// dictionary 아이템 추가
var cities = [String: String]()
cities["JP"] = "Tokyo"
cities["KR"] = "Seoul"
print(cities) // 출력값: ["KR": "Seoul", "JP": "Tokyo"]


// dictionary 아이템 추가 및 수정
// updateValue(_:forKey:): 만약 기존에 저장된 키가 있으면 연결된 값을 수정 이전의 값 return
// 새로운 키가 입력되면 아이템 추가하고 nil을 return한다.
print(cities.updateValue("Korea", forKey: "KR")) // 출력값: Optional("Seoul")

print(cities["KR"]) // 출력값: Optional("Korea")

print(cities.updateValue("China", forKey: "CH")) // 출력값: nil

print(cities["CH"]) // 출력값: Optional("China")


// 딕셔너리 순회 탐색
// 딕셔너리는 고유 키에 대한 해시 값을 기준으로 내부 정렬하기 때문에 실행할때마다 다르게 출력될 수 있다.
for (key, value) in cities {
    print("\(key)은/는 \(value)입니다")
}

// 출력값
// JP은/는 Tokyo입니다
// KR은/는 Korea입니다
// CH은/는 China입니다


// 배열과 동일하게 remove, count, isEmpty, contains 사용


Set

같은 타입의 서로 다른 값을 중복 없이 저장하고자 할 때 사용하는 집단 자료형
집합은 순서가 중요하지 않은 데이터들이거나 중복없이 한 번만 저장되어야하는 데이터들을 다룰 때 배열 대신 사용할 수 있는 자료형이다.
해시 연산을 할 수 있는 타입만 저장 가능하다.

// 빈 집합 만들기, 집합 초기화
// 타입을 지정하지않으면 컴파일러가 배열로 인식하기 때문에 집합 타입이라는 것을 명시적으로 기재해주어야 한다.
var emptySet = Set<String>()
var genres: Set<String> = []


// 집합 아이템 추가하기
genres.insert("Classic")
genres.insert("Rock")

print(genres) // 출력값: ["Classic", "Rock"]


// 집합 순회 탐색
// 집합의 속성으로 순서가 보장되지 않기 때문에 실행할때마다 다르게 출력된다.
for g in genres {
    print("\(g)")
}

// 출력값: Rock Classic


// sorted(): 정렬된 결과를 받을 수 있지만 집합 자체의 순서를 결정하는 것은 아니고 단지 메서드의 반환값을 정렬하는 것이다.
print(genres.sorted())
// 출력값: ["Classic", "Rock"]


// 배열에서 중복 아이템을 제거하는 방법
var A = [4,2,5,1,7,4,9,11,3,5,4] // 배열
let B = Set(A) // 집합
A = Array(B) // 중복이 제거된 배열
print(A.sorted())
// 출력값: [1, 2, 3, 4, 5, 7, 9, 11]


// 배열과 동일하게 remove, count, isEmpty, contains 사용 가능

집합 연산

var oddDigits: Set = [1,3,5,7,9] // 홀수 집합
let evenDigits: Set = [0,2,4,6,8] // 짝수 집합
let primeDigits: Set = [2,3,5,7] // 소수 집합

//intersection(_:): 교집합
oddDigits.intersection(evenDigits).sorted()
// 출력값: []

// symmetricDifference(_:): 여집합
oddDigits.symmetricDifference(primeDigits).sorted()
// [1,2,9]

// union(_:): 합집합
oddDigits.union(evenDigits).sorted()
// [0,1,2,3,4,5,6,7,8,9]

// subtract(_:): 차집합
oddDigits.subtract(primeDigits)
oddDigits.sorted()
// [1,9]


let A: Set = [1,3,5,7,9]
let B: Set = [3,5]
let C: Set = [3,5]
let D: Set = [2,4,6]

// isSubset(of:): 하나의 집합이 다른 집합의 부분집합인지 판단
B.isSubset(of: A) // true

// isSuperset(of:): 집합이 다른 집합이 상위집합인지 판단
A.isSuperset(of: B) // true

// isStrictSubset(of:): 하나의 집합이 다른 집합의 부분집합인지 판단, 두 집합이 서로 같은 경우의 결과값이 다르게 반환
C.isStrictSubset(of: A) // true
C.isStrictSubset(of: B) // false

// isDisjoint(with:): 두 집합 사이의 공통 값을 확인하여 아무런 공통 값이 없을때 true, 공통 값이 하나라도 있으면 false를 반환
A.isDisjoint(with: D) // true


Tuple

하나의 튜플에 여러 가지 타입의 아이템을 저장할 수 있지만, 선언되고 나면 상수적 성격을 띠므로 값 추가나 삭제 등 변경이 불가능하다.
튜플은 대괄호를 사용하는 배열이나 집합과 달리 소괄호를 이용하여 정의한다.

// 튜플 정의
let aTuple = ("a", "b", 1, 2.5, true)

// 인덱스 속성을 이용해 참조 가능
aTuple.0 // "a"
aTuple.1 // "b"
aTuple.2 // 1 
aTuple.3 // 2.5
aTuple.4 // true

// 튜플은 별도 선언 구문은 없지만 타입 어노테이션을 사용하기 위한 타입을 정의할 수 있다.
var tpl1: (Int, Int) = (100,200)
var tpl2: (Int, String, Int) = (100, "a", 200)


// 튜플의 아이템을 개별 변수나 상수로 각각 할당받는 바인딩(Binding) 방식의 구문도 제공된다.
let bTuple: (String, Character, Int) = ("a", "b", 1)
let (a,b,c) = bTuple

print(a) // 출력값: a
print(b) // 출력값: b
print(c+2) // 출력값: 3


// 함수나 메서드에서 둘 이상의 값을 반환할 때 별도의 자료형 객체를 만들거나 배열 또는 딕셔너리를 만들어야 하는데, 이때 튜플을 이용하면 편리하다.
func getTupleValue() -> (String, Int) {
    return("t", 100)
}

let (a,b) = getTupleValue()

print(a) // 출력값: t
print(b) // 출력값: 100

1개의 댓글

comment-user-thumbnail
2023년 7월 28일

좋은 글 감사합니다. 자주 올게요 :)

답글 달기