본문 바로가기

SWIFT 공식문서 문법 알아보기/04. Collection Types

Swift 공식문서 해설 Collection Types - Mutability of Collections, Arrays (4-1)

집단 자료형 (Collection Types)

스위프트는 집단 자료형을 저장하기 위해 잘 알려진 arrays, sets, dictionaries 3가지 주요한 collection types을 제공합니다. 배열은 순서대로 값을 모았습니다. 집합은 순서 없는 고유 값의 모음입니다. 딕셔너리는 순서 없이 키 값의 연관성의 모음입니다.

 

스위프트에서 배열, 집합, 딕셔너리는 저장할 수 있는 값과 키의 타입에 대해 항상 명확하게 합니다. 이 말인즉슨 실수로 로 잘못된 타입의 자료형에 값을 넣을 수 없습니다. 또한 집단으로부터 되찾아올 값이 어떤 자료형인지에 대해 자신감이 있을 수 있습니다.  

NOTE

스위프트의 배열, 집합, 딕셔너리 자료형은 generic collections으로 실행됩니다. generic types과 collections에 대해 알고 싶다면 Generics를 보세요.

Mutability of Collections

만약 배열, 집합, 딕셔너리를 만들고 변수를 할당했다면 생성된 집단은 변할 수 있습니다. 그 말인즉슨 추가, 제거, 혹은 집단에서의 항목을 변경하는 것으로 집단을 변경할 수 있습니다. 만약 배열, 집합, 딕셔너리를 상수로 할당했다면 집단은 변할 수 없게 되며 크기와 내용도 변경할 수 없습니다. 

NOTE

집단이 변할 필요가 없는 모든 경우에 변하지 않는 집단을 만드는 것은 좋은 습관입니다. 위와 같이 만든다면 코드에 대한 추론을 쉽게 할 수 있으며 스위프트의 컴파일러를 통해 만든 집단의 성능을 최대한 좋게 만들 수 있습니다. 

배열 (Arrays)

배열은 같은 자료 유형을 가진 값을 순서화된 목록으로 저장합니다. 동일한 값은 다른 위치로 여러 번 나타날 수 있습니다. 

NOTE

스위프트는 배열은 Foundation’s NSArray class의 가교 역할을 합니다. 

배열을 사용하는 Foundation and Cocoa에 대해 더 알고 싶다면 Bridging Between Array and NSArray 확인하세요.

Array Type Shorthand Syntax

스위프트의 배열 타입은 Array <Element>로 쓸 수 있고 Elemet는 저장할 수 있는 배열의 값에 대한 타입입니다. 또한 배열에 대한 타입을 [Element]의 축약형으로 쓸 수 있습니다. 2개의 형태가 기능적으로 같지만 축약형 형태가 더 많이 선호되고 공식문서에서 배열의 타입을 언급할 때 축약형을 계속 사용할 것입니다. 

Creating an Empty Array

초기화 문법을 사용하여 특정한 타입의 빈 배열을 만들 수 있습니다. 

 

var someInts = [Int]()
print("someInts is of type [Int] with \(someInts.count) items.")
// Prints "someInts is of type [Int] with 0 items."

 

someInts의 변수는 [Int] 타입으로 초기화했기 했으므로 [Int]로 추론됩니다. 만약 문맥상으로 함수 혹은 이미 변수나 상수로 타입이 정해졌을 경우와 같이 타입에 대한 정보를 제공한다면 빈 배열의 리터럴 값을 가진 빈 배열을 []을 사용하여 만들 수 있습니다. 

 

someInts.append(3)
// someInts now contains 1 value of type Int
someInts = []
// someInts is now an empty array, but is still of type [Int]

 

Creating an Array with a Default Value

스위프트 배열의 타입은 모든 값이 기본값으로 설정되어 있는 특정 크기의 배열을 만들기 위한 초기화를 제공합니다. repeating라고 불려지는 적절한 타입의 기본값을 초기화하고 count라고 불리는 새로운 배열에 값이 몇 번 반복되는지 넣습니다.

 

var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]

Creating an Array by Adding Two Arrays Together

덧셈 연산자를 활용하여 타입이 호환되는 2개의 배열을 합쳐서 새로운 배열을 만들 수 있습니다. 새로운 배열의 타입은 합쳐지는 2개의 배열으로부터 추론됩니다.

 

var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
// anotherThreeDoubles is of type [Double], and equals [2.5, 2.5, 2.5]

var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles is inferred as [Double], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]

Creating an Array with an Array Literal

배열 literal을 사용한 배열을 초기화를 할 수 있으며 배열 모음에 한 개 혹은 그 이상의 값을 쓰기 위한 축약 방식입니다. 배열 literal은 대괄호로 둘러싼 후 콤마에 의해 리스트의 값들이 분리됩니다.

 

[value 1, value 2, value 3]

 

아래의 예는 문자열 값을 저장하기 위해 shoppingList라고 불리는 배열을 만들었습니다. 

 

var shoppingList: [String] = ["Eggs", "Milk"]
// shoppingList has been initialized with two initial items

 

shoppingList 변수는 [String]으로 쓰인 문자열 값 배열로 선언되었습니다. 문자열 타입의 값으로 명시된 배열이기 때문에 오직 문자열 값만 저장이 가능합니다. shoppingList 배열은 배열 literal로 쓰인 2개의 문자열 값("Eggs" and "Milk")을 초기화했습니다.

NOTE

shoppingList 상수가 아니라 변수로 선언되었습니다. 왜냐하면 아래의 예처럼 더 많은 쇼핑 리스트에 많은 아이템들을 추가할 수 있기 때문입니다.

 

이 경우 배열 literal은 2개의 문자열 값 외에는 어떤 것도 포함하지 않습니다. shoppingList 타입을 일치시켜 선언한 것은 (오직 문자열 값만 표함 시켜 배열한 것) 할당된 배열 literal은 2개의 아이템으로 shoppingList를 초기화하기 위한 방법으로 허용됩니다. 스위프트의 타입 추론 덕분에 같은 타입의 값을 포함하는 배열 literal을 초기화하려고 한다면 배열의 타입을 적을 필요가 없습니다. 

shoppingList의 초기화는 더 짧은 형태로 작성이 가능합니다.

 

var shoppingList = ["Eggs", "Milk"]

 

배열 literal의 모든 값은 같은 타입이기 때문에 스위프트는 [String]이 shoppingList 변수에 맞는 타입이라고 추론할 수 있습니다.

Accessing and Modifying an Array

배열은 methods and properties을 통해 접근과 수정이 가능하고 혹은 subscript 문법으로도 가능합니다. 

배열 안의 아이템 개수를 찾기 위해 읽기 전용인 count 속성으로 확인합니다.  

 

print("The shopping list contains \(shoppingList.count) items.")
// Prints "The shopping list contains 2 items."

 

isEmpty 속성의 Boolean값을 사용하여 count의 속성이 0인지 아닌지 빠르게 확인할 수 있습니다.

 

if shoppingList.isEmpty {
print("The shopping list is empty.")
} else {
print("The shopping list is not empty.")
}
// Prints "The shopping list is not empty."

 

배열의 아이템 끝에 새로운 아이템을 추가하기 위해 배열의 append(_:) method를 쓸 수 있습니다. 

 

shoppingList.append("Flour")
// shoppingList now contains 3 items, and someone is making pancakes

 

다른 대안으로는 추가 할당 연산자를(+=) 활용해서 배열에 한 개 혹은 그 이상 호환이 가능한 아이템을 덧붙일 수 있습니다.

 

shoppingList += ["Baking Powder"]
// shoppingList now contains 4 items
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
// shoppingList now contains 7 items

 

subscript 문법을 사용하여 배열으로부터 반환되는 값은 반환되길 원하는 값의 인덱스 번호를 대괄호 안에 넣는다면 즉시 배열에서의 이름을 알 수 있습니다. 

 

var firstItem = shoppingList[0]
// firstItem is equal to "Eggs"

NOTE

배열에서의 첫 번째 아이템은 1이 아니라 0입니다. 스위프트에서의 배열은 항상 0 인덱스입니다.

subscript문법으로 존재하는 값의 주어진 인덱스를 변경할 수 있습니다. 

 

shoppingList[0] = "Six eggs"
// the first item in the list is now equal to "Six eggs" rather than "Eggs"

 

subscript 문법을 사용할 때 구체적으로 지정한 인덱스가 유효해야 합니다. 예를 들어 배열의 끝에 아이템을 추가하기 위해 shoppingList [shoppingList.count]= "Salt"를 작성하면 런타임 오류가 발생합니다.

subscript문장으로 한 번에 범위의 값을 변경할 수 있고 설정되어 있는 값이 바꾸려고 하는 범위보다 길이가 다르더라도 가능합니다. 아래의 예를 보면 "Chocolate Spread", "Cheese", "Butter"를 "Bananas" and "Apples"로 변경합니다.

 

shoppingList[4...6] = ["Bananas", "Apples"]
// shoppingList now contains 6 items

 

배열 안에 특정한 인덱스에 아이템을 넣고 싶다면 배열의 insert(_:at:) method를 사용합니다.

 

shoppingList.insert("Maple Syrup", at: 0)
// shoppingList now contains 7 items
// "Maple Syrup" is now the first item in the list

 

insert(_:at:) method는 쇼핑 리스트 가장 맨 처음인 인덱스 0 값에 "Maple Syrup"이라는 새로운 아이템의 값을 넣습니다. 

이와 유사하게 remove(at:) method을 사용하여 아이템을 제거할 수 있습니다. 이 method는 구체적인 인덱스의 아이템을 제거하고 제거된 아이템을 반환합니다. (반환된 값이 필요 없다면 무시할 수 있습니다)

 

let mapleSyrup = shoppingList.remove(at: 0)
// the item that was at index 0 has just been removed
// shoppingList now contains 6 items, and no Maple Syrup
// the mapleSyrup constant is now equal to the removed "Maple Syrup" string

NOTE

만약 배열의 존재하는 범위 밖의 인덱스 값을 접근하거나 수정하려고 한다면 런타임 오류가 발생할 것입니다. 배열의 count 속성을 비교하여 사용하기 전에 인덱스 값이 유효한지 확인할 수 있습니다. 배열에서 유효한 인덱스에서 가장 큰 숫자에서 -1해야 합니다. 왜냐하면 배열의 인덱스는 0부터 시작하기 때문입니다. 그러나 count가 0일(배열이 비어있다는 의미) 때 유효한 인덱스는 없습니다. 

 

배열에서 아이템이 사라질 때 배열의 공백은 없어지고 인덱스 0의 값은 "Six eggs"가 됩니다.

 

firstItem = shoppingList[0]
// firstItem is now equal to "Six eggs"

 

만약 배열에서 마지막 아이템을 제거하고 싶다면 remove(at:) method 보다 removeLast() method를 사용하는 것이 배열의 count 속성 사용을 피하기 위해 좋습니다.

remove(at:) method 마찬가지로 removeLast()도 제거된 아이템을 반환받습니다. 

 

let apples = shoppingList.removeLast()
// the last item in the array has just been removed
// shoppingList now contains 5 items, and no apples
// the apples constant is now equal to the removed "Apples" string

Iterating Over an Array

for-in loop를 사용하여 배열의 전체 지정된 값을 반복할 수 있습니다.

 

for item in shoppingList {
print(item)
}
// Six eggs
// Milk
// Flour
// Baking Powder
// Bananas

 

만약 각각의 아이템의 정수형 인덱스 값과 값이 필요하다면 enumerated() method를 사용하여 배열 전체를 반복할 수 있습니다. enumerated() method는 배열의 각각의 아이템에 대해 정수와 아이템의 튜플로 구성되어 값을 반환합니다. 정수는 0에서 시작하고 각 아이템마다 1씩 카운트가 올라가고 만약 전체 배열을 열거하면 정수들은 아이템 인덱스와 일치합니다. 반복의 일부를 일시적으로 상수나 변수로 tuple을 분리할 수 있습니다. 

 

for (index, value) in shoppingList.enumerated() {
print("Item \(index + 1): \(value)")
}
// Item 1: Six eggs
// Item 2: Milk
// Item 3: Flour
// Item 4: Baking Powder
// Item 5: Bananas

 

for-in loop에 대해 자세히 알고 싶다면 여기를 참고하세요.

 

 

Swift 공식문서 해설 Control Flow - For-In Loops, While Loops (5-1)

스위프트는 다양한 control flow 문장을 제공합니다. while loop는 어떤 일을 여러 번 시키는 데 사용하고 if, guard, switch 구문은 특정 상황에 따라 다른 코드를 실행시키며 break, continue와 같은 문장은 코..

iosbeginner.tistory.com