C와 Objective-C에서는 다음과 같이 코드를 작성해 9x7 크기의 쿠키 그리드를 만들 수 있다.
int cookies[9][7];
이 코드는 63개의 요소를 가진 2차원 배열을 생성한다. 3번째 컬럼과 6번째 행에 있는 쿠키를 찾으려면 다음과 같이 작성한다.
myCookie = cookies[3][6];
하지만 이 문법은 Swift에서 사용할 수 없다. Swift에서 다차원 배열을 생성하려면 다음과 같이 작성한다.
var cookies = [[Int]]()
for _ in 1...9 {
var row = [Int]()
for _ in 1...7 {
row.append(0)
}
cookies.append(row)
}
그런 다음, 쿠키를 찾으려면 다음과 같이 작성한다.
let myCookie = cookies[3][6]
또한, 배열을 한 줄로 생성할 수도 있다.
var cookies = [[Int]](repeating: [Int](repeating: 0, count: 7), count: 9)
이 코드는 복잡해 보이지만, 헬퍼 함수를 사용해 간단히 만들 수 있다.
func dim<T>(_ count: Int, _ value: T) -> [T] {
return [T](repeating: value, count: count)
}
그러면 배열을 다음과 같이 생성할 수 있다.
var cookies = dim(9, dim(7, 0))
Swift는 배열 요소의 기본값으로 0
을 지정했기 때문에 배열의 데이터 타입이 Int
임을 추론한다. 문자열을 사용하려면 다음과 같이 작성한다.
var cookies = dim(9, dim(7, "yum"))
dim()
함수를 사용하면 더 많은 차원의 배열도 쉽게 만들 수 있다.
var threeDimensions = dim(2, dim(3, dim(4, 0)))
하지만 이렇게 다차원 배열이나 중첩된 배열을 사용하면 각 차원이 무엇을 의미하는지 헷갈릴 수 있다.
대신, 2차원 배열처럼 동작하는 커스텀 타입을 만들어 사용하면 더 편리하다.
public struct Array2D<T> {
public let columns: Int
public let rows: Int
fileprivate var array: [T]
public init(columns: Int, rows: Int, initialValue: T) {
self.columns = columns
self.rows = rows
array = .init(repeating: initialValue, count: rows*columns)
}
public subscript(column: Int, row: Int) -> T {
get {
precondition(column < columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
precondition(row < rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
return array[row*columns + column]
}
set {
precondition(column < columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
precondition(row < rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
array[row*columns + column] = newValue
}
}
}
Array2D
는 제네릭 타입이므로 숫자뿐만 아니라 모든 종류의 객체를 저장할 수 있다.
Array2D
의 인스턴스를 생성하려면 다음과 같이 작성한다.
var cookies = Array2D(columns: 9, rows: 7, initialValue: 0)
subscript
함수를 사용해 배열에서 객체를 가져올 수 있다.
let myCookie = cookies[column, row]
또는 값을 변경할 수도 있다.
cookies[column, row] = newCookie
내부적으로 Array2D
는 데이터를 저장하기 위해 단일 1차원 배열을 사용한다. 객체의 인덱스는 (행 x 컬럼 수) + 컬럼
으로 계산되지만, Array2D
를 사용하는 개발자는 "컬럼"과 "행"만 생각하면 되며, 나머지 세부 사항은 Array2D
가 처리한다. 이렇게 기본 타입을 래퍼 클래스나 구조체로 감싸는 것이 장점이다.
Swift Algorithm Club의 Matthijs Hollemans가 작성함