배열정의 및 선언 - 스위프트(swift)
배열(Arrays)이란?
일련의 순서를 가지는 리스트 형식의 값을 저장하는 데에 사용되는 자료형임
배열에서는 인덱스를 이용하여 배열 내에 있는 아이템을 읽어 올 수 있음
특징
- 배열에 저장할 아이템의 타입에는 제약이 없지만, 하나의 배열에 저장된 아이템 타입은 모두 일치해야함
- 선언시 배열에 저장할 아이템 타입을 명확히 정의해야함
- 동적으로 배열의 크기를 확장할 수 있음
인덱스(Index)란?
배열에 입력되어 있는 개별 아이템들은 모두 순서가 있는데 이 순서를 인덱스(Index)라고 함
인덱스 특징
- 정수로 이루어져 있음
- 0부터 시작하여 아이템이 추가될 떄마다 차례대로 증가함
배열에서 인덱스
아이템의 순서를 나타내고, 아이템이 있는 위치를 알려주는 역할이 전부
-순서대로 할당됨
-중간에 값을 생략하거나 건너뛰는 경우가 없음
-인덱스에 연결된 아이템이 삭제되면 인접한 아이템이 차례대로 앞으로 이동하면서 빈 인덱스를 채워 넣음
따라서, 배열의 처음이나 중간에 있는 아이템이 삭제되어도 실제로 사라지는 인덱스는 마지막 인덱스임
배열을 정의하는 방법은 두가지임 (정적, 동적)
1) 정적(static)
- 처음부터 배열을 구성하는 아이템을 포함하여 정의하는 방식
*장점
- 별도의 배열 선언이 필요없음
- 배열을 정의할 떄 대괄호를 사용하며, 대괄호 내에 차례대로 아이템을 나열하면 아이템을 품은 배열이 만들어짐
[ 아이템1, 아이템2, 아이템3 ...]
여기서 cities는 String타입의 변수가 아니고 배열 타입으로 선언된 변수임(타입추론에 의하여)
배열을 이루는 아이템에 모두 리터럴이 직접 사용되었기 때문에 cities는 문자열 아이템을 가지는 배열임
리터럴(Literal) 이란?
변수나 상수에 담긴 형태가 아니라 그에 저장되는 값 자체를 리터럴이라 뜻함
이렇게 생성한 배열의 각 아이템은 인덱스를 사용하여 참조할 수 있음
배열을 대입한 변수나 상수에 대괄호를 붙이고 원하는 아이템에 해당하는 인덱스를 입력하면 됨
인덱스는 0부터 시작하기 때문에 아이템도 0부터 순서대로 번호를 할당받음
때문에 마지막 인덱스는 배열의 크기보다 1만큼 적음
배열의 순회 탐색
순회 탐색 뜻??
순서가 있는 데이터를 처음부터 마지막까지 차례대로 읽어 들이는 것
배열 순회탐색 때 for ~ in 구문을 많이 사용함
배열 순회탐색은 두가지로 나눌 수 있음
1) 배열의 길이를 직접 다루는 방식
* 배열의 길이 = 배열에 들어가 있는 아이템의 개수
배열의 길이를 구해서 이 횟수만큼 루프가 반복되도록 직접 구현하는 것을 말함
- 최소한 한 줄의 코드가 더 필요
- 배열 자체에 의존하지 않고 원하는 만큼 횟수를 늘리거나 줄일 수 있음
-몇 번을 반복해서 아이템을 읽어 들어야 배열이 끝나는지 결정하기 위해,
배열 내에 아이템이 몇개가 있는지 먼저 알아야 함
스위프트에서는 배열의 길이를 구할때 배열 변수나 상수에 .count를 붙여줌
.count 속성을 이용하여 얻은 배열의 크기를 상수 length에 할당하고,
0에서 시작한 카운터 변수가 이크기만큼 커질때까지 for ~ in 구문을 반복함
꿀팁)
배열 순회 할때에는 반 닫힌 연산자를 사용하는게 좋음
이유 : 0부터 시작하는 배열 인덱스의 특성상 마지막 인덱스 값이 항상 배열의 크기보다 1이 적기때문에
반 닫힌 연산자를 사용하면 배열의 크기 값을 포함하지 않는 범위까지 가져오기 떄문임
TMI
for i in 0..<cities.count { // 상수를 정의하지 않고 직접 사용
실행구문
}
배열 크기를 상수에 할당하지 않고 직접 .count를 사용하게 되면 for ~ in 구문은 루프를 반복할 때마다 배번 조건식을 평가하게 됨
이때 배열크기를 매번 다시 계산하게 되는데 이는 전체적인 실행속도를 느리게 하여 문제가 될 소지를 가진 방식임.
2) 배열의 순회 특성{이터레이터(Iterator)}을 이용하는 방식
- for ~ in 구문에 배열 자체를 넣어서 실행시키는 것을 의미
for ~ in 구문이 읽어 들인 배열을 따라 순회하기 시작하면
배열의 아이템들이 차례대로 추출되어 for 와 in 사이에 정의된 루프 상수에 할당됨
index(of:)
아이템을 통해 인덱스 값을 역으로 찾을 수 있음
index(of: )는 메소드로 배열의 아이템을 넣으면 그 아이템이 배열의 몇번째 인덱스에 저장되어 있는지 알려주는 역할
배열의 인덱스를 확인하여 index 상수에 대입
배열의 정적인 선언을 알아 보았고 이제 동적인 선언에 대하여 알아봅세~
배열을 정의할때 한꺼번에 필요한 아이템을 몽땅 집어넣고 정적으로 정의하여 사용하는 경우보다
선언과 초기화만 해 놓은 후 필요에 따라서 그때그때 동적으로 아이템을 추가하는 경우가 훨씬 많음
2) 배열 동적 선언
Array <아이템 타입> ()
스위프트에서 배열을 정의하는 객체는 Array임
배열을 정의할 때에는 반드시 저장할 아이템의 타입도 함께 명시해 주어야함
* 컴파일러는 이때 입력받은 아이템 타입을 이용하여 다른 데이터 타입이 입력되었을 경우 잘못 입력되었음을 판단함
배열 내부의 아이템을 바로 아이템 타입 형태로 사용할 수 있도록 처리해주기도함
이처럼 사용 시점에서 <> 기호를 사용하여 배열 내부에서 사용할 아이템 타입을 지정하는 문법을 제네릭(Generic)이라고 함
예시)
문자열 아이템 저장할 배열 <String>
정수 아이템 저장할 배열 <Int>
범용 클래스 객체를 저장할 배열< AnyObject>
동적으로 배열을 정의할 때에는 선언과 초기화 과정이 차례로 필요함
선언은(Declare)은 요러한 배열을 만들꺼임을 컴파일러에게 미리 알려주는 역할
초기화(initialization)은 앞서 말한 선언한 것을 실제로 만들어주세요라고 요청하는 과정임
배열 구조체는 선언만 되었을때 메모리 공간을 차지하지 않다가
초기화가 진행이 되면 그때서야 메모리 공간을 할당 받아 데이터를 저장할 수 있는 공간이 생기는 거임
배열에서 선언과 초기화를 동시에 처리하는 예시
var cities = Array<String>()
문자열 배열 객체를 정의한다음 cities 변수에 대입함
이렇게 되면 빈배열로 초기화됨
만약 선언만하고 싶으면 경우에는 다음 예시처럼 하면 됨
var cities = Array<String>
이렇게 선언만 할 경우 메모리 공간을 할당받지 않은 상태임
초기화를 해서 메모리를 할당 받아야 함
초기화의 경우에는 다음 예시처럼 하면 됨
cities = Array()
cities 변수는 이미 타입 어노테이션을 통해 배열의 저장 타입이 지정되어 있음
TMI
Q: 만약에 이미 선언과 초기화가 이루어진 배열 변수를 또다시 초기화하면 어떻게 될까??
A: 기존 배열은 제거되고 배열 객체가 다시 만들어져 변수에 할당됨
스위프트에서 배열을 정의하는 다른 형식
[ 아이템 타입 ] ()
배열 선언과 초기화
var cities = [String]()
선언과 초기화를 분리하였을때
배열 선언
var cities = [String]
배열 초기화
//첫번째 초기화 방식
cities = [String]()
//두번째 초기화 방식
cities = []
첫번째 방식은 선언된 배열 그대로를 초기화
두번째 방식은 빈배열을 하나 만들어서 이것을 변수에 할당함
이 두번째 방식을 초기화가 아님
배열 선언은 이처럼 다양하므로 사용하고 싶은 형태로 사용하면 됨
첫번째방법
var cities : [String] //선언
cities = [String]() //초기화
두번째방법
var country : [String] //선언
country = [] //초기화
세번째방법
var list : [Int] = [] //타입 어노테이션 + 초기화
네번째방법
var rows : Array<Float> = [Float]() //타입 어노테이션 + 제네릭 + 초기화
다섯번째방법
var tables : [String] = Array() // 타입 어노테이션 + 구방식의 초기화
IsEmpty
선언된 배열이 비어 있는지를 체크해야 할때
배열 구조체에서 제공하는 속성인 isEmpty를 사용하는 것이 좋음
배열에 아이템이 없는 텅 빈상태일시 true
배열에 아이템이 있을 경우 false를 반환함
(.count를 이용하여 0이냐 아니냐도 가능하긴함)
*이때 isEmpty 속성은 읽기 전용 이므로 true를 대입할 수 없음