Swift 기초문법 - Array 배열 정리하기

오늘은 Swift Collection의 한 종류인 Array 배열 사용에 대해서 알아봅시다. 컬렉션은 수많은 데이터를 묶어 저장하고 관리할 수 있는 데이터 타입입니다. 

 

Aarray 배열

배열은 순서를 가지고, 같은 데이터 타입을 저장할 수 있는 컬렉션입니다. 각각의 요소는 순번이 있습니다. 이것을 Index(인덱스)라고 부르고, 배열의 인덱스를 통해서 각각 요소들에 접근할 수 있습니다. 컴퓨터는 0에서 시작하기 때문에 인덱스 역시 0부터 시작합니다. 4개의 Element가 있다면 0 -> 3까지가 됩니다. 

 

Array 배열 생성

let numbers: [Int] = [1, 2, 3, 4]
let numbers: Array<Int> = [1, 2, 3, 4]

Swift Array 배열을 생성하는 방법 입니다. [데이터 타입] 형태와 Array<데이터 타입>입니다. [데이터 타입]이 간단해서 더 많이 선호한다고 합니다. 배열 역시 let을 사용하면 추가로 요소를 넣어주거나 삭제할 수 없습니다. 

 

var initZeroArr = [Int](repeating: 0, count: 5)
//[0, 0, 0, 0, 0]

고정된 수의 기본값으로 미리 초기화된 배열이 필요한 경우에는 Array(repeating : count :)를 이용하면 만들 수 있습니다. repeating 값으로 count 만큼의 배열이 초기화된 상태로 만들어집니다. 

 

Array 배열에 요소 추가하기

var numbers: [Int] = [1, 2, 3, 4]

numbers.append(5)
numbers.append(contentsOf: [8, 9])
numbers += [6, 7]

배열에 요소를 추가하는 방법입니다. 배열의 끝에 단일 요소를 추가할 때에는 append(값)을 사용하면 됩니다. append(contentsOf :) 메서드를 이용하면 다른 배열이나 여러 요소를 동시에 추가할 수 있습니다. 또한 배열에서 +덧셈 연산자를 사용 해서 배열을 추가할 수 있습니다. C++에서는 연산자 재정의를 통해서 += 같은 연산자를 덧셈의 기능이 아닌 다른 기능으로 사용할 수 있습니다. Swift에서도 비슷 한 방법으로 함수를 만들었을 듯합니다.

 

var numbers: [Int] = [1, 2, 3, 4]
numbers.insert(5, at: 0)
numbers.insert(contentsOf: [6, 7], at: 3)

// 결과 : [5, 1, 2, 3, 4]
// 결과 : [5, 1, 2, 6, 7, 3, 4]

insert 함수를 통해서 해당 인덱스 위치에 요소를 추가할 수 도 있습니다. 2번째 줄은 at : 인덱스 0번 인덱스 위치에 5를 넣었습니다. 5가 0번 인덱스에 추가되고, 기존 배열의 값들이 뒤로 밀린 걸 볼 수 있습니다. 3번째 줄은 3번 인덱스 위치에 [6, 7]을 넣었습니다. 인덱스 3의 값(3)이 위치한 자리에 6, 7이 추가된 걸 볼 수 있습니다. 

 

Array 배열에서 요소 삭제하기

var numbers: [Int] = [1, 2, 3, 4, 5]

numbers.remove(at: 0)
// 결과 : [2, 3, 4, 5]

numbers5.removeSubrange(0...1)
// 결과 : [4, 5]

numbers5.removeAll();
// 결과 : []

remove함수를 통해서 배열의 요소를 삭제하는 방법입니다. at: 인덱스 0번 인덱스의 값을 지웁니다. 0번 인덱스의 값인 1이 지워진 결과를 볼 수 있습니다. 요소 삭제를 할 때에 range도 이용할 수 있습니다. removeSubrange 파라미터로는 인덱스 범위를 넘겨줍니다. 0...1 은 0번 인덱스부터 1번 인덱스까지 지우는 호출입니다. 2, 3이 삭제되었네요. removeAll은 감이 오시죠? 모든 배열의 요소를 삭제시키는 함수입니다. 

 

Array 배열 요소 접근하기

var numbers: [Int] = [1, 2, 3, 4, 5]
let firstIndexValue = numbers[0]
// 결과 : 1

let secondIndexValue = numbers[1]
// 결과 : 2

let lastIndexValue = numbers[4]
// 결과 : 5

numbers[4] = 10
// 결과 : [1, 2, 3, 4, 10]

let errorIndexValue = numbers[10]
// 결과 : error 
//error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).

배열 안에 있는 요소에 접근하는 방법입니다. Array[유효한 인덱스] 를 통해서 접근할 수 있습니다. 11번째 라인을 봅시다. 배열의 인덱스로 요소의 값을 변화시키면 배열 안의 값이 바뀌게 됩니다. 4번째 인덱스의 값이 5에서 10으로 변화한 것을 볼 수 있습니다. 그리고 배열을 사용할 때에 가장 중요한 것인데요. 배열에 할당된 메모리를 벗어난 인덱스를 이용할 경우에는 에러가 발생합니다. 현재 numbers는 5개의 요소를 가지고 있고 유효한 인덱스는 0 ~ 4 까지 입니다. 하지만 10번째 인덱스 값에 접근하였기 때문에 에러가 발생하게 된 것이죠.

error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).

 

var numbers: [Int] = [1, 2, 3, 4, 5]
print(numbers.first)
// 결과 : Optional(1)
print(numbers.last)
// 결과 : Optional(5)

if let firstIndexValue = numbers.first {
    print(firstIndexValue)
}
// 결과 : 1

if let lastIndexValue = numbers.last {
    print(lastIndexValue)
}
// 결과 : 5

배열에서는 인덱스를 몰라도 first와 last를 사용하면 첫 번째와 마지막 요소에 접근할 수 있습니다. 그런데 결과를 보면 Optional로 되어있습니다. 바로 배열이 비어있을 수도 있기 때문이죠. 비어있는 배열의 첫 번째 혹은 마지막 인덱스에 접근하게 되면 당연히 문제가 발생하겠죠? 

 

Array 배열 확인하기

var numbers: [Int] = [1, 2, 3, 4, 5]
numbers.isEmpty		// 결과 : false
numbers.count		// 결과 : 5
numbers5.capacity	// 결과 : 5
numbers.append(6)	// 결과 : [1, 2, 3, 4, 5, 6]
numbers.count		// 결과 : 6
numbers.capacity	// 결과 : 10

배열의 상태를 확인하는 방법입니다. isEmpty 값으로 현재 배열이 비어있냐를 체크할 수 있습니다. 타입은 bool입니다. 현재 배열은 비어있지 않기 때문에 false입니다. count는 배열의 현재 요소가 몇 개 인지를 확인할 수 있습니다. 그러면 capacity는 뭘까요? 용량이라는 뜻인데요. 바로 배열에 잡혀있는 메모리 크기입니다. 배열은 연속된 메모리 블럭을 가지는데요. 메모리 블럭의 크기라고 생각 하면 됩니다.

코드를 보시면 처음 배열의 count, capacity가 동일한 걸 볼 수 있습니다. 하지만 6을 추가하게 되면 count, capacity의 결과가 달라지는데요. 그 이유는 처음 메모리 블럭의 크기가 5이고 이미 5개의 요소가 할당되어있죠. 그렇기 때문에 6을 추가하려면 공간이 부족하게 됩니다. 따라서 메모리 블럭의 크기를 키우고 기존 메모리 블럭을 복사한 후 6을 추가하는 것이죠.

 

var numbers: [Int] = []
numbers.reserveCapacity(10)
numbers.count		// 결과 : 0
numbers.capacity	// 결과 : 10

모든 배열은 특정 양의 메모리를 예약하고 있습니다. 하지만 미리 할당된 메모리의 크기를 초과하게 되면 더 큰 메모리 영역을 할당하고 기존 요소들을 새롭게 할당된 메모리에 복사를 합니다. 새롭게 할당된 메모리는 기존 크기의 배수가 됩니다. 이렇게 할당 복사는 성능에 있어서 좋지 않습니다. 저장할 요소의 수를 대략 알고 있거나 재할당을 피하기 위해서는 reserveCapacity를 이용할 수 있습니다. 배열은 비어있지만 이렇게 예약을 하게 되면 count는 요소가 없어서 0이지만 capacity는 10이 된 것을 볼 수 있습니다. 10개의 요소를 넣을 때 까지는 메모리 재할당이 발생하지 않게 되죠.

 

정리

Swift 배열의 모든 함수를 다 볼 수 없기 때문에 기본적인 것들만 설명했습니다. 저도 다 사용을 해보지 못했기 때문이기도 합니다. 추가적인 것들은 추후에 사용해 보면서 설명해보겠습니다.

그리드형(광고전용)

이 글을 공유합시다

facebook twitter googleplus kakaoTalk kakaostory naver band

댓글

Designed by JB FACTORY