Swift의 2D 배열에 대해 너무 혼란 스러워요. 단계별로 설명하겠습니다. 그리고 제가 틀렸다면 제발 정정 해 주시겠습니까?
가장 먼저; 빈 배열 선언 :
class test{
var my2Darr = Int[][]()
}
두 번째로 배열을 채 웁니다. (예를 들어 my2Darr[i][j] = 0
i, j는 for 루프 변수)
class test {
var my2Darr = Int[][]()
init() {
for(var i:Int=0;i<10;i++) {
for(var j:Int=0;j<10;j++) {
my2Darr[i][j]=18 /* Is this correct? */
}
}
}
}
그리고 마지막으로 배열의 요소 편집
class test {
var my2Darr = Int[][]()
init() {
.... //same as up code
}
func edit(number:Int,index:Int){
my2Darr[index][index] = number
// Is this correct? and What if index is bigger
// than i or j... Can we control that like
if (my2Darr[i][j] == nil) { ... } */
}
}
답변
가변 배열 정의
// 2 dimensional array of arrays of Ints
var arr = [[Int]]()
또는:
// 2 dimensional array of arrays of Ints
var arr: [[Int]] = []
또는 미리 정의 된 크기의 배열이 필요한 경우 (주석에서 @ 0x7fffffff에 언급 됨) :
// 2 dimensional array of arrays of Ints set to 0. Arrays size is 10x5
var arr = Array(count: 3, repeatedValue: Array(count: 2, repeatedValue: 0))
// ...and for Swift 3+:
var arr = Array(repeating: Array(repeating: 0, count: 2), count: 3)
위치에서 요소 변경
arr[0][1] = 18
또는
let myVar = 18
arr[0][1] = myVar
하위 배열 변경
arr[1] = [123, 456, 789]
또는
arr[0] += 234
또는
arr[0] += [345, 678]
이러한 변경 이전에 0 (영)의 3×2 배열이 있었다면 이제 다음과 같이됩니다.
[
[0, 0, 234, 345, 678], // 5 elements!
[123, 456, 789],
[0, 0]
]
따라서 하위 배열은 변경 가능하며 행렬을 나타내는 초기 배열을 재정의 할 수 있습니다.
액세스하기 전에 크기 / 경계를 검토하십시오.
let a = 0
let b = 1
if arr.count > a && arr[a].count > b {
println(arr[a][b])
}
설명 :
3 차원 및 N 차원 배열에 대해 동일한 태그 규칙.
답변
문서에서 :
대괄호 쌍을 중첩하여 다차원 배열을 만들 수 있습니다. 여기서 요소의 기본 유형 이름은 가장 안쪽 대괄호 쌍에 포함됩니다. 예를 들어 대괄호 세 세트를 사용하여 정수의 3 차원 배열을 만들 수 있습니다.
var array3D: [[[Int]]] = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
다차원 배열의 요소에 액세스 할 때 가장 왼쪽에있는 첨자 인덱스는 가장 바깥 쪽 배열의 해당 인덱스에있는 요소를 참조합니다. 오른쪽에있는 다음 아래 첨자 인덱스는 한 수준에 중첩 된 배열의 해당 인덱스에있는 요소를 나타냅니다. 등등. 즉, 위의 예에서 array3D [0]은 [[1, 2], [3, 4]], array3D [0] [1]은 [3, 4], array3D [0] [1 ] [1]은 값 4를 나타냅니다.
답변
Generic Swift 4로 만들기
struct Matrix<T> {
let rows: Int, columns: Int
var grid: [T]
init(rows: Int, columns: Int,defaultValue: T) {
self.rows = rows
self.columns = columns
grid = Array(repeating: defaultValue, count: rows * columns) as! [T]
}
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> T {
get {
assert(indexIsValid(row: row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
assert(indexIsValid(row: row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
var matrix:Matrix<Bool> = Matrix(rows: 1000, columns: 1000,defaultValue:false)
matrix[0,10] = true
print(matrix[0,10])
답변
을 사용할 때주의해야합니다 Array(repeating: Array(repeating: {value}, count: 80), count: 24)
.
값이로 초기화 된 객체 인 MyClass()
경우 동일한 참조를 사용합니다.
Array(repeating: Array(repeating: MyClass(), count: 80), count: 24)
MyClass
각 배열 요소에 의 새 인스턴스를 만들지 않습니다 . 이 메서드는 MyClass
한 번만 생성 하여 배열에 넣습니다.
다음은 다차원 배열을 초기화하는 안전한 방법입니다.
private var matrix: [[MyClass]] = MyClass.newMatrix()
private static func newMatrix() -> [[MyClass]] {
var matrix: [[MyClass]] = []
for i in 0...23 {
matrix.append( [] )
for _ in 0...79 {
matrix[i].append( MyClass() )
}
}
return matrix
}
답변
Swift 4에서
var arr = Array(repeating: Array(repeating: 0, count: 2), count: 3)
// [[0, 0], [0, 0], [0, 0]]
답변
swift 4.1에 대한 Apple 문서에 따르면이 구조체를 매우 쉽게 사용하여 2D 배열을 만들 수 있습니다.
코드 샘플 :
struct Matrix {
let rows: Int, columns: Int
var grid: [Double]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(repeating: 0.0, count: rows * columns)
}
func indexIsValid(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> Double {
get {
assert(indexIsValid(row: row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
assert(indexIsValid(row: row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}
답변
Swift에서 다차원 배열을 사용하기 전에 성능에 미치는 영향을 고려하십시오 . 내 테스트에서 평면화 된 배열은 2D 버전보다 거의 2 배 더 나은 성능을 보였습니다.
var table = [Int](repeating: 0, count: size * size)
let array = [Int](1...size)
for row in 0..<size {
for column in 0..<size {
let val = array[row] * array[column]
// assign
table[row * size + column] = val
}
}
50×50 어레이를 채우기위한 평균 실행 시간 : 82.9ms
대
var table = [[Int]](repeating: [Int](repeating: 0, count: size), count: size)
let array = [Int](1...size)
for row in 0..<size {
for column in 0..<size {
// assign
table[row][column] = val
}
}
50×50 2D 어레이를 채우기위한 평균 실행 시간 : 135ms
두 알고리즘 모두 O (n ^ 2)이므로 실행 시간의 차이는 테이블을 초기화하는 방식에 의해 발생합니다.
마지막으로 할 수 있는 최악 의 상황 은 append()
새 요소를 추가 하는 데 사용 하는 것입니다. 그것은 내 테스트에서 가장 느린 것으로 판명되었습니다.
var table = [Int]()
let array = [Int](1...size)
for row in 0..<size {
for column in 0..<size {
table.append(val)
}
}
append ()를 사용하여 50×50 배열을 채우기위한 평균 실행 시간 : 2.59 초
결론
다차원 배열을 피하고 실행 속도가 중요한 경우 인덱스 별 액세스를 사용하십시오. 1D 배열은 성능이 더 우수하지만 코드를 이해하기가 조금 더 어려울 수 있습니다.
내 GitHub 저장소 ( https://github.com/nyisztor/swift-algorithms/tree/master/big-o-src/Big-O.playground) 에서 데모 프로젝트를 다운로드 한 후 성능 테스트를 직접 실행할 수 있습니다.
