스위프트의 2차원 배열
Swift의 2D 어레이에 대해 너무 혼란스럽습니다.단계별로 설명하겠습니다.그리고 제가 틀렸다면 수정해 주시겠습니까?
우선, 빈 배열 선언:
class test{
var my2Darr = Int[][]()
}
두 번째로 배열을 채웁니다.(예:my2Darr[i][j] = 0
여기서 i, jare for-loop 변수)
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? */
}
}
}
}
그리고 마지막으로, inarray의 요소를 편집합니다.
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]]()
OR:
// 2 dimensional array of arrays of Ints
var arr: [[Int]] = []
또는 미리 정의된 크기의 배열이 필요한 경우(댓글에서 @0x7ffffff가 언급한 대로):
// 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
OR
let myVar = 18
arr[0][1] = myVar
하위 배열 변경
arr[1] = [123, 456, 789]
OR
arr[0] += 234
OR
arr[0] += [345, 678]
이러한 변경 전에 0(제로)의 3x2 배열이 있었다면 이제 다음과 같습니다.
[
[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]]]
다차원 배열의 요소에 액세스할 때 가장 왼쪽에 있는 첨자 인덱스는 가장 바깥쪽 배열의 해당 인덱스에 있는 요소를 참조합니다.오른쪽의 다음 첨자 인덱스는 배열에서 한 수준으로 중첩된 해당 인덱스의 요소를 나타냅니다.등등.이것은 위의 예에서 배열3을 의미합니다.D[0]는 [1, 2], [3, 4], 배열 3을 말합니다.D[0][1]은 [3, 4]를 참조하며 배열3D[0][1][1]은 값 4를 나타냅니다.
제네릭 스위프트 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
}
인 스위프트 4
var arr = Array(repeating: Array(repeating: 0, count: 2), count: 3)
// [[0, 0], [0, 0], [0, 0]]
Apple의 swift 4.1 문서에 따르면 이 구조를 매우 쉽게 사용하여 2D 배열을 만들 수 있습니다.
링크: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Subscripts.html
코드 샘플:
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
}
}
50x50 어레이 채우기의 평균 실행 시간: 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
}
}
50x50 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()를 사용하여 50x50 어레이를 채우는 평균 실행 시간: 2.59초
결론
실행 속도가 중요한 경우 다차원 배열을 피하고 인덱스별 액세스를 사용합니다. 1D 어레이가 더 성능이 좋지만 코드를 이해하기가 조금 더 어려울 수 있습니다.
내 GitHub repo: https://github.com/nyisztor/swift-algorithms/tree/master/big-o-src/Big-O.playground 에서 데모 프로젝트를 다운로드한 후 직접 성능 테스트를 실행할 수 있습니다.
Swift 5.5에서
2D 어레이를 어떻게 장착할 수 있는지 이해하기 위한 것입니다.
import UIKit
var greeting = "Hello, playground"
var arrXY = [[String]]()
// 0 1 2 3
arrXY.append(["A","B","C","D"]) // 0
arrXY.append(["E","F","G","H"]) // 1
arrXY.append(["J","K","L","M"]) // 2
arrXY.append(["N","O","P","Q"]) // 3
print(arrXY)
print(arrXY[2][1]) // xy(2,1)
print(arrXY[0][3]) // xy(0,3)
print(arrXY[3][3]) // xy(3,3)
이 작업은 한 줄로 간단하게 수행할 수 있습니다.
스위프트 5
var my2DArray = (0..<4).map { _ in Array(0..<) }
원하는 클래스 또는 구조의 인스턴스에 매핑할 수도 있습니다.
struct MyStructCouldBeAClass {
var x: Int
var y: Int
}
var my2DArray: [[MyStructCouldBeAClass]] = (0..<2).map { x in
Array(0..<2).map { MyStructCouldBeAClass(x: x, y: $0)}
}
Swift 버전 5.5
이 버전에서는 기본 옵션 배열을 사용하여 어설션 사용으로 인해 발생할 수 있는 런타임 오류를 방지합니다.
struct Matrix<T> {
let numberOfRows: Int
let numberOfColumns: Int
var elements: [T?]
/// Creates a new matrix whose size is defined by the specified number of rows and columns.
/// containing a single, repeated optional value.
///
/// - Parameters:
/// - repeatedValue: The element to repeat
/// - numberOfRows: The number of rows
/// - numberOfColumns: The number of columns
init(repeating repeatedValue: T? = nil, numberOfRows: Int, numberOfColumns: Int) {
// counts must be zero or greater.
let numberOfRows = numberOfRows > 0 ? numberOfRows : 0
let numberOfColumns = numberOfColumns > 0 ? numberOfColumns : 0
self.numberOfRows = numberOfRows
self.numberOfColumns = numberOfColumns
self.elements = Array(repeating: repeatedValue, count: numberOfRows * numberOfColumns)
}
subscript(row: Int, column: Int) -> T? {
get { elements[(row * numberOfColumns) + column] }
set { elements[(row * numberOfColumns) + column] = newValue }
}
}
저는 1D 어레이를 사용하고 인덱스만 따로 작성할 것입니다.예를 들어 다음을 사용해 보십시오.
struct MatrixIndexer {
var rows: Int
var columns: Int
var count: Int {
return rows * columns
}
subscript(_ r: Int, _ c: Int) -> Int {
precondition(r < rows && c < columns)
return r * columns + c
}
func coordinate(_ i: Int) -> (row: Int, column: Int) {
precondition(i < count)
return (i / columns, i % columns)
}
}
let at = MatrixIndexer(rows: 16, columns: 8)
var array2D: [Float] = Array(repeating: 0, count: at.count)
array2D[at[3, 4]] = 3
array2D[at[5, 2]] = 6
(단일구을통려면다같입다니합력이음과키시과물조)▁(다▁an▁(단니▁to입▁you합력▁introduce▁struct▁around,같▁single▁you이▁couldif▁pass)를 도입할 수 있습니다.Array2D
를포는하가 .MatrixIndexer
리고그.Array
).
왜 이게 좋은 생각일까요?첫째, 다음과 같은 보다 효율적인 운영이 가능합니다.
- 컬렉션 확장명: 맵, 필터, 축소
- 단일 루프에서 모든 요소 반복
- 쉬운 복사
- 각 행과 열의 크기가 동일한지 여부를 확인합니다.
둘째로, 그것은 또한 성능 면에서도 훨씬 더 좋습니다.
- 메모리 할당을 줄임으로써 액세스 시간을 단축합니다.각 행이 메모리에서 별도의 점이 되는 대신 각 요소는 다음 요소와 인접합니다.
- 많은 명령 대신 하나의 할당 및 할당 취소 명령을 사용합니다(할당자는 다양한 이유로 느려지는 경우가 많습니다).
당신이 사용한다면 때때로 그것은 일을 더 간단하게 만드는 것을 도울 수 있습니다.typealias
기본 배열 유형에 해당합니다.은 은다음 2D 예니다의 입니다.String
:
typealias Strings = [String]
let stringGroups: [Strings] // aka [[String]]
언급URL : https://stackoverflow.com/questions/25127700/two-dimensional-array-in-swift
'programing' 카테고리의 다른 글
이전 버전과의 호환성을 위해 Debian의 MySQL 또는 MariaDB에 자동으로 연결하는 API 안정적인 방법 (0) | 2023.08.23 |
---|---|
Spring Boot Repository와 DAO의 API 비교 (0) | 2023.08.23 |
AJAX 및 페이지를 떠나는 사용자 (0) | 2023.08.23 |
Javascript를 사용하여 메타 새로 고침 태그 재정의 또는 비활성화 (0) | 2023.08.23 |
빌드 프로세스가 없는 Vue.js 단일 파일 구성 요소 (0) | 2023.08.23 |