배열(Arrays)은 일련의 순서를 가지는 리스트 형식의 값을 저장하는 데에 사용되는 자료형으로, 약간씩의 차이는 있지만 많은 프로그래밍 언어가 공통적으로 제공하는 자료형이기도 하다. 배열에 입력되는 개별 아이템들은 모두 각각의 순서가 있는데, 이 순서를 일련번호, 즉 인덱스(index)라고 한다. 배열에서는 인덱스를 사용하여 배열 내 아이템을 읽어올 수 있다. 인덱스는 정수로 이루어지며, 0부터 시작하여 아이템이 추가될 때마다 차례대로 증가하는 것이 특징이다.
배열에서 인덱스는 순서대로 할당되며, 중간에 값을 생략하거나 건너뛰는 경우는 없다. 인덱스에 연결된 아이템이 삭제되더라도 인접한 다음 아이템들이 차례대로 앞으로 이동하면서 빈 인덱스를 채워 넣는다. 배열 처음이나 중간에 있는 아이템이 삭제되더라도 실제로 사라지는 인덱스는 맨 마지막 인덱스이다.
이런 특성 때문에 인덱스는 배열의 아이템과 생사고락을 같이하는 고유 코드 역할을 할 수 없다. 그저 아이템의 순서를 나타내고, 아이템이 있는 위치를 가리키는 역할만 할 뿐이다. 중복된 인덱스가 없고 배열의 아이템이 바뀌지 않는 이상 인덱스와 아이템 간의 연결이 바뀌지만 않지만, 배열 내에서 아이템을 삭제하면 그 다음 아이템과 연결되므로 사용 시 주의해야 한다.
스위프트에서 사용하는 배열 자료형은 몇 가지 특징이 있다.
- 배열에 저장할 아이템의 타입에는 제한이 없지만, 하나의 배열에 저장하는 아이템의 타입은 모두 같아야 한다.
- 선언 시 배열에 저장할 아이템 타입을 명확히 정의해야 한다.
- 배열의 크기는 동적으로 확장할 수 있다.
정적 방식 배열 정의
[ 아이템1, 아이템2, 아이템3, ...]
var cities = ["Seoul", "New York", "LA", "Santiago"]
배열 순회 탐색
순서가 있는 데이터를 처음부터 마지막까지 차례대로 읽어 들이는 것을 순회 탐색이라고 한다. 순회 탐색에는 주로 반복문이 사용되는데, 반복문의 특성상 비교적 간단하게 데이터를 순회할 수 있는 방법을 제공하기 때문이다. 배열 또한 순서가 있는 데이터이므로 반복문을 사용하여 순회 탐색을 할 수 있다.
배열의 순회 특성, 즉 이터레이터를 이용하여 순회 탐색을 진행한다.
for ~ in 구문은 순번을 가진 범위 데이터를 넣으면 데이터의 크기만큼 반복 실행 되는 특성이 있다. 이 특성을 이용하여 for ~ in 구문에 배열 데이터를 직접 넣으면 간편하게 배열을 순회할 수 있다.
var cities = ["Seoul", "New York", "LA", "Santiago"]
// 배열의 순회 특성을 사용하여 탐색
for city in cities {
print("배열 원소는 \(city)입니다.")
}
// 결과값
// 배열 원소는 Seoul입니다.
// 배열 원소는 New York입니다.
// 배열 원소는 LA입니다.
// 배열 원소는 Santiago입니다.
순회 특성을 이용하여 배열을 탐색하면 루프 상수에 담기는 값은 현재의 인덱스 값이 아니라 배열 아이템 자체이므로, 몇 번째 아이템인지 인덱스를 바로 알기 어렵다. 이 때 firstIndex(of:)를 사용하면 아이템을 통해 인덱스 값을 역으로 찾을 수 있다.
var cities = ["Seoul", "New York", "LA", "Santiago"]
for city in cities {
// 배열의 인덱스를 확인하여 index 상수에 대입
let index = cities.firstIndex(of: city)
print("\(index!)번째 배열 원소는 \(city)입니다.")
}
// 결과값
// 0번째 배열 원소는 Seoul입니다.
// 1번째 배열 원소는 New York입니다.
// 2번째 배열 원소는 LA입니다.
// 3번째 배열 원소는 Santiago입니다.
배열의 동적 선언과 초기화
배열을 정의할 때 한꺼번에 필요한 아이템을 모두 집어넣고 정적으로 정의하여 사용하는 경우보다 선언과 초기화만 해 놓은 이후 필요에 따라서 그때그때 동적으로 아이템을 추가하는 경우가 훨씬 많다.
동적으로 배열을 정의하는 방법은 총 두가지 형식으로 사용할 수 있다.
Array <아이템 타입> ()
스위프트에서 배열으 정의하는 객체는 Array이다. 구조체로 정의된 이 객체는 실질적인 배열 데이터를 만드는 데 사용될 뿐만 아니라 배열에서 데이터를 효과적으로 다루기 위한 다양한 기능을 제공한다.
사용 시점에서 <>기호를 사용하여 배열 내부에서 사용할 아이템 타입을 지정하는 문법을 제네릭(Generic)이라고 한다.
var cities = Array<String>()
var cities : Array<String> // 문자열 배열을 선언
cities = Array() // 배열의 초기화
문자열 형식의 배열 객체를 정의한 다음, cities 변수에 대입하고 있다. 아래는 위 내용을 나누어 보여준다.
아래는 다른 타입의 선언과 초기화 과정이다.
[아이템 타입] ()
// 배열 선언 & 초기화
var cities = [String]()
var cities : [String] // 배열 선언
cities = [String]() // 배열 초기화 - 첫번째 방식
cities = [] // 배열 초기화 - 두번째 방식
배열 아이템 동적 추가
배열에 동적으로 아이템을 추가할 때에는 메소드를 사용하는데, 기능에 따라 다양한 메소드가 있지만 대표적인 것으로 아래 세 가지 정도를 사용한다.
- append(_:)
- insert(_:at:)
- append(contentsOf:)
append(_:) 메소드는 입력된 값을 배열의 맨 뒤에 추가한다. 일반적으로 배열에서 존재하지 않는 인덱스에 접근하면 오류가 발생하므로 이 메소드는 아이템 추가 전에 먼저 배열의 크기를 +1만큼 확장하여 인덱스 공간을 확보한 후, 인자값으 마지막 인덱스 위치에 추가한다.
반면 insert(_:at:) 메소드는 아이템을 배열의 맨 뒤가 아닌 원하는 위치에 직접 추가하고 싶을 때 사용한다. at:뒤에 입력되는 정수값은 배열에서 아이템이 추가될 인덱스의 위치를 의미한다. 이 인덱스에 새로운 값이 추가되면 이를 기준으로하여 나머지 인덱스들은 하나씩 다음으로 밀려나는 결과를 가져온다. 쉽게 말해 끼어들기라고 생각하면 편하다.
마지막으로 append(contentsOf:)는 append(_:) 메소드처럼 배열의 맨 마지막에 아이템을 추가하지만, 개별 아이템이 아니라 여러 개의 아이템을 배열에 한꺼번에 추가할 때 사용하는 메소드이다. 이를 위해 메소드의 인자값은 항상 배열이어야 한다.
아래는 메소드를 이용하여 배열 아이템을 동적으로 추가한 것이다.

범위 연산자를 이용한 인덱스 참조
배열의 인덱스를 지정해서 개별 아이템을 참조하는 방식 이외에도 범위 연산자를 이용하면 특정 범위의 인덱스에 해당하는 아이템을 모두 참조할 수 있다. 주로 일정 범위의 배열 아이템을 한꺼번에 읽어 들일 때 사용하는데, 사용하는 방식은 아래와 같다.

범위 연산자를 이용해 배열의 데이터를 바꾸는 예시이다.

'swift' 카테고리의 다른 글
| 스위프트 튜플 (0) | 2024.04.08 |
|---|---|
| 스위프트 집합 (1) | 2024.04.06 |
| 스위프트 집단 자료형 (1) | 2024.04.06 |
| 스위프트 제어 전달문 (1) | 2024.04.06 |
| 스위프트 조건문 (0) | 2024.04.06 |