본문 바로가기

iOS/Swift

Swift) Array - 자주 사용하는 메서드

 

 

 

안녕하세요 :) 소들입니다

이번 포스팅에선 배열을 사용할 때 알아두면 편한 메서드들을 좀 정리해보려고 해요!!!
요즘 자료구조 쪽을 공부하다보니 언어에 대한 포스팅이 적은 것 같아서 🌚

힙(Heap)을 포스팅할까.. Swift를 할까.. 하다가 Swift로 정해버렸음니다

 

원래 설명충이긴 한데

이번 포스팅만큼은 단순 명료하게 가겠슴니다!!

(물론 설명할 게 있는 부분은 설명충임 :))

 

모든 포스팅은 편의 말투로 합니다~!!

 

 

 

.

.

.

자 먼저..!!!

배열 메서드를 알기 전에 Swift의 배열에 대해서 먼저 알고 가겠움 :)

여러분 Swift에선 총 두 개의 배열이 존재함!!

 

그것은 Swift에서 제공하는, 우리가 평소에 사용하는 Array라는 것이고,

나머지 하나는 Foundation에서 제공하는 NSArray라는 것임!! (Objective-C 문법)

 

이 둘의 차이점은 다음과 같음 :)

 

 

  Array NSArray
타입 구조체 타입 클래스 타입
저장 위치 스택(Stack) 힙(Heap)
요소(Element) 자료형 모두 동일한 자료형만 저장 가능
(Int형 배열은 Int형만 저장 가능,
String형 배열은 String형만 저장 가능)
인스턴스라면 타입 상관 없이 저장 가능
(Int, Double 같은 구조체 타입은 저장 불가,
NSNumber 같은 인스턴스로는 저장 가능.
인스턴스기만 한다면 NSString, NSNumber 등 타입에 상관 없이 하나의 배열에 모두 저장 가능)
COW(Copy-on-write) O X

 

 

자, 이런 차이점이 있음!!

근데, 보통 사용하는 것은 Array이기 때문에 Array의 메서드에 대해 다룰 것임!!!!

 

 

 

 

1. 배열 생성하기

 

 

// 1. 타입 추론으로 생성하기
var array1 = [123]
var array2 = []                 // error! 타입 추론으론 빈 배열 생성 불가
 
 
// 2. 타입 Annotation으로 생성하기
var array3: [Int= [123]
var array4: [Int= []          //빈 배열 생성
 
 
// 3. 생성자로 생성하기
var array5 = Array<Int>()
var array6 = [Int]()
var array7 = [Int](repeating: 0, count: 10)   //생성과 동시에 10개 Element 생성 및 0으로 초기화

 

 

보통  간편한 1번이나 2번의 방법을 많이 사용함!!!

나 같은 경우엔 Type Annotation을 좋아해서 2번을 많이 씀 :)

 

녀러분 Swift는 타입에 굉~~~~장히 민감한 언어임!!! 

  선언과 동시에 Type을 꼭 명시하거나 추론할 수 있게 해주어야 하고,

해당 Type으로 된 값만 배열에 저장할 수 있음!!!

 

따라서 만약 난 배열 한 개에 여러 타입을 저장하고 싶은데??? 라고 한다면,

Type을 Any로 선언하거나, Objective-C의 클래스인 NSArray를 사용하면 됨

 

 

// 4. 여러 타입을 저장하는 배열 생성하기
var array8: [Any= [1"Sodeul"20.4]
var array9: NSArray = [1"Sodeul"20.4]

 

 

앞서 잠깐 말했 듯이

NSArray는 Class 형식이라 요소는 무조건 "인스턴스"로 구성되어 있어야 함..!

때문에 위에서 array8에 삽입한 1, 20.4 라는 숫자는 Int, Double형이 아니라,

NSNumber라는 인스턴스로 저장

 

왜냐? Int, Double형은 구조체 타입이기 때문에 인스턴스가 아니거든!

근데, 이럴 경우 Swift가 Array를 구조체로 만든 이유(Stack으ㅣ 장점)이 사라지고...

 

혹은 Any를 사용한다고 하면 런타임 시에 타입을 알 수 있기 때문에 컴파일 시 실행 오류를 잡기도 힘들고,

너무 추상적인 타입이라..  절대 남발하진 말길..!

(웬만해선 Array만 써도 거의 다 되긴 함)

 

 

 

 

2. 배열 갯수 확인하기

 

 

var array1 = [123]

let countInt = array1.count      // 배열 갯수 확인 : 3
let isEmptyBool = array1.isEmpty // 배열 비었는지 확인 : false

 

 

만약 배열이 비었는지를 확인하고 싶다면

array1.count == 0 이 구문보단, array1.isEmpty를 사용합시다 :)

 

 

 

 

3. 배열 요소에 접근하기

 

 

var array1 = [123]

// 1. Subscript로 접근하기
array1[0]        // 1
array1[1]        // 2
 
// 2. 범위로 접근하기
array1[0...1]    // [1, 2]
 
// 3. 속성으로 접근하기
array1.first     // Optional(1)
array1.last      // Optional(3)

 

 

Subscript라는 것은 우리가 흔히 배열에 대괄호([])로 접근하는 것을 말함..!

근데 Subscript나 범위로 접근하는 것은 위험성이 있음

 

위 주석 결과값에서도 알 수 있듯이 반환형이 Non-Optional Type임..!

따라서 만약 해당 index에 해당하는 값이 없으면 그것은 에러로 빠짐

 

따라서 만약 첫번째, 마지막 요소에 접근할 것이면

Subscript보다 first, last란 속성을 사용하는 것이 안전함 :)

이것들은 리턴 타입이 Optional Type이라서 만약 값이 없으면 에러가 아닌 nil을 리턴

 

 

 

 

4. 배열에 요소 추가하기

 

 

// 1. append : 끝에 추가
var array1 = [123]
array1.append(4)                            // [1, 2, 3, 4]
array1.append(contentsOf: [567])        // [1, 2, 3, 4, 5, 6, 7]
 
// 2. inset : 중간에 추가
var array2 = [123]
array2.insert(0, at: 0)                      // [0, 1, 2, 3]
array2.insert(contentsOf: [10100], at: 2)  // [0, 1, 10, 100, 2, 3 ]

 

 

배열에 요소 추가는 appendinsert로 할 수 있는데,

contentsOf 파라미터를 사용하면 배열에 배열을 붙일 수도 있음

 

근데 한 가지 유의할 점!!

자료구조 할 때 귀에 딱지앉게 말했지만 배열의 경우, insert 시에 오버헤드가 발생함

 

 

 

 

배열의 경우 index로 접근하기 때문에,

insert를 해주면 insert를 하는 위치부터 배열을 재배치 해야 하기 때문에

오버헤드가 발생하는 것임!

 

때문에, 꼭 필요한 경우를 제외하곤 append를 쓰자!

 

 

 

 

5. 배열 요소 변경하기

 

 

배열 안에 저장된 요소의 값을 변경하고 싶을 때 쓰는 것

 

 

// 1. Subscript로 변경하기
var array1 = [123]
array1[0= 10                       // [10, 2, 3]
array1[0...2= [102030]         // [10, 20, 30]
array1[0...2= [0]                  // [0]
array1[0..<1= []                   // []
 
// 2. replaceSubrange로 바꾸기 (범위 변경 시)
var array2 = [123]
array2.replaceSubrange(0...2, with: [102030])     // [10, 20, 30]
array2.replaceSubrange(0...2, with: [0])              // [0]
array2.replaceSubrange(0..<1, with: [])               // []

 

 

 

 

6. 배열 요소 삭제하기

 

 

// 1. 일반적인 삭제하기
var array1 = [123456789]
 
array1.remove(at: 2)             // [1, 2, 4, 5, 6, 7, 8, 9]
array1.removeFirst()             // [2, 4, 5, 6, 7, 8, 9]  
array1.removeFirst(2)            // [5, 6, 7, 8, 9]
array1.removeLast()              // [5, 6, 7, 8]&
array1.popLast()                 // [5, 6, 7]
array1.removeLast(2)             // [5]
array1.removeAll()               // []
 
// 2. 특정 범위 삭제하기
var array2 = [123456789]
 
array2.removeSubrange(1...3)     // [1, 5, 6, 7, 8, 9]
array2[0..<2= []               // [6, 7, 8, 9]

(함수 설명 밑에 표로 정리해뒀으니 표랑 결과랑 같이 보셈)

 

함수 이름 용도 리턴 타입
remove(at:) 파라미터로 받은 index에 해당하는 값 삭제  삭제된 값 리턴
Non-Optional Type
removeFirst 첫 번째 요소 삭제 삭제된 값 리턴
Non-Optional Type
removeFirst(_:) 첫 번째 요소부터 파라미터로 받은 갯수 만큼 삭제  X
removeLast 마지막 요소 삭제 삭제된 값 리턴
Non-Optional Type
popLast 마지막 요소 삭제 삭제된 값 리턴
Optional Type
removeLast(_:) 마지막 요소부터 파라미터로 받은 갯수 만큼 삭제 X
removeAll 전체 요소 삭제 X
removeSubrange(_:) 파라미터로 받은 범위만큼 index 요소 삭제 X
[n...m] = [] Subscript 문법으로 n ~ m까지 index 요소 삭제 X

 

자, 어려운 내용 하나도 없음 :)

removeLast는 리턴 값이 Non-Optional Type이라,

마지막 값이 없을 경우 에러를 내지만, popLast는 리턴 값이 Optional Type이기 때문에

마지막 값이 없을 경우 nil을 돌려주고 에러를 내지 않음!

 

따라서 removeLast 보단 조금 더 안전한 popLast를 쓰자 :))

아, 참고로 remove 역시 마지막 요소를 삭제하는 것이 아니면 insert와 같은 이유로 오버헤드가 발생

 

 

 

 

7. 배열 비교하기

 

 

var array1 = [123]
var array2 = [123]
var array3 = [12345,]
 
array1 == array2                    //true
array1.elementsEqual(array3)        //false

 

 

모든 요소가 같아야만 true임!

 

 

 

 

8. 배열 요소 검색하기

 

 

var array1 = [123456789]

// 1. contains : 해당 값이 배열에 존재하는지 Bool로 리턴
array1.contains(1)                //true
array1.contains(10)               //false
 
// 1-1. contains + 클로저 : 직접 검색 구도를 구현 (예제 : 짝수가 하나라도 있으면 true)
array1.contains { num in          // true
    num % 2 == 0
}
 
// 2. first + 클로저 : 클로저의 조건을 만족하는 가장 첫 번째 요소의 "값"을 리턴, 없다면 nil을 리턴
array1.first { num in             // Optional(2)
    num % 2 == 0
}
 
// 3. firstIndex + 클로저 : 클로저의 조건을 만족하는 가장 첫 번째 요소의 "Index"을 리턴, 없다면 nil을 리턴
array1.firstIndex { num in        // Optional(1)
    num % 2 == 0
}
 
// 4. last + 클로저 : 클로저의 조건을 만족하는 가장 마지막 요소의 "값"을 리턴, 없다면 nil을 리턴
array1.last { num in              // Optional(6)
    num % 2 == 0
}
 
// 5. lastIndex + 클로저 : 클로저의 조건을 만족하는 가장 마지막 요소의 "Index"을 리턴, 없다면 nil을 리턴
array1.lastIndex { num in         // Optional(5)
    num % 2 == 0
}
 

 

 

상황에 맞게 잘 사용해보셈 :)

 

 

 

 

9. 배열 정렬하기

 

 

let array1 = [153861014]
 
// 1. sort : 배열을 직접 "오름차순"으로 정렬
array1.sort()                                         // [1, 3, 5, 6, 8, 10, 14]
 
// 1-1. sort + 클로저 : 배열을 직접 "내림차순"으로 정렬
array1.sort(by: >)                                    // [14, 10, 8, 6, 5, 3, 1]
 
 
// 2. sorted : 원본은 그대로 두고, "오름차순"으로 정렬된 새로운 배열을 만들어 리턴
let sortedArray = array1.sorted()                     // [1, 3, 5, 6, 8, 10, 14]
 
// 2-1. sorted + 클로저 : 원본은 그대로 두고, "내림차순"으로 정렬된 새로운 배열을 만들어 리턴
let sortedArray2 = array1.sorted(by: >)               // [14, 10, 8, 6, 5, 3, 1]

 

 

여러분 sortsorted의 차이점에 대해 헷갈리시는 분들이 있을텐데,

보통 Swift에서 함수 이름 동사

 

-ing

-ed

 

가 붙는 것들은 원본을 건드리지 않고,

작업이 완료된 새로운 것을 리턴함...!!!

 

따라서 sort동사 그대로이니 원본을 건드는 것이고,

sorted는 -ed가 붙었으니 원본은 건들지 않고 정렬된 새로운 배열을 리턴하는 것임..!

 

이 내용은 sort/sorted 뿐 아니라 Swift 함수 대부분에 적용되니까 알아두면 꿀팁임 :)

 

 

 

 

10. 배열 요소 바꾸기

 

 

let array1 = [12345]
array1.swapAt(04)         // [5, 2, 3, 4, 1]

 

 

요론 것도 된다!!! 매우 간편하군 :)

 

 

 

 

11. 배열 무작위로 섞기

 

 

let array1 = [12345]
array1.shuffle()            // [5, 2, 1, 4, 3]

 

 

이런 기능도 있음..ㅋㅋ

 

 

 

+ 만약 배열 순회(for - in, forEach) 등에 대해 알고 싶으신 분은

이 포스팅을 참조해주센~~

 

.

.

.

 

배열을 사용할 때 어쩌면 필수고 어쩌면 알아두면 좋은

메서드들 정리 끝 :)

 

읽으시는 모든 분께 도움이 됐길 ~.~

배열 fast enumeration 사용하는 방법은 (배열 for in 사용법 같은 거)

나중에 Collection 다 묶어서 따로 포스팅 할 것임 !!!!

또한 더 많은 메서드들을 알게되면 추가 할게영 :D

 

잘못된 내용, 피드백, 궁금증은 언제나 댓글 주세요 💩

그럼 20,000



Calendar
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
최근 댓글
Visits
Today
Yesterday