THIS IS ELLIE

dropFirst(_:), removeFirst(_:) 살펴보기 본문

개발/Swift

dropFirst(_:), removeFirst(_:) 살펴보기

Ellie Kim 2020. 9. 16. 03:20

오늘은 dropFirst(_:)와 removeFirst(_:)를 정리해보도록 하겠습니다.

 

사실 알고리즘 문제 풀다가... 스위프트는 왜 비슷한 메서드들을 정의해놨는지 궁금했습니다.

당연히 차이가 있으니깐 비슷한 것들을 따로 생성했겠죠...ㅎㅎ?

(나: 제발 좀 공부해라)

 

알고리즘 문제를 보고 아! 이문제는 재귀 쓰자 마음먹었고...

재귀를 사용했어요.

그리고 재귀는 언제 리턴될지가 중요하잖아요.

저는 빈 배열이 될 때를 제약 조건으로 두고 재귀를 돌렸습니다.

 

즉 빈 배열이 나올 때까지 재귀로 들어가고

파라미터로는 배열의 첫 번째 요소를 제거한 나머지 배열을 계속 전달했어요.

 

여기서부터 사건의 발달 ... 

배열의 첫 번째 요소를 제거한 나머지 배열을 전달하는 방법에 대해서 생각하다가 두 가지가 떠올랐어요.

 

문제를 가져오기엔 너무 길어서 example함수로 대체했습니다.

 

첫 번째 방법

dropFirst(_:) 사용

func example(_ nums: [Int]) {
    guard nums.count > 0 else {
        return
    }
    
    example(Array(nums.dropFirst()))
}

 

 

 

두 번째 방법

removeFirst(_:) 사용

func example(_ nums: [Int]) {
    guard nums.count > 0 else {
        return
    }
    
    var copy = nums    
    copy.removeFirst()
    
    example(copy)
}

 

다른 여러 방법이 존재하겠지만, 저는 이렇게 두 가지가 떠올랐어요.

 

일단 두 가지 방법 모두 배열의 첫 번째 요소를 제거한 나머지 배열을 파라미터로 전달하는 역할을 하고

차이점이 있다면 dropFirst(_:) 메서드는 파라미터로 받은 상수 배열에 직접 사용하고 리턴 받은 subsequece을 배열로 형변환하여 파라미터로 전달했고 removeFirst(_:) 메서드는 수정 가능하도록 변수 배열을 생성하여 사용했고 수정된 배열을 파라미터로 전달했다는 차이가 있었습니다.

 

그리고 공식 문서를 살펴보았습니다.


주어진 수만큼의 초기 element를 제외하고 모든 것을 포함하는 subsequence를 리턴합니다.

그리고 아래와 같이 선언되어 있습니다.

func dropFirst(_ k: Int = 1) -> ArraySlice<Element>

선언된 부분을 살펴보면 매개변수 k는 컬렉션의 시작 부분에서 몇 개 삭제할지 정하는 것이고 이는 0보다 크거나 같아야 합니다.

k는 1이 디폴트 값이네요. 

그리고 subsequence인 ArraySlice<Element>로 리턴합니다. 

 

제공된 예시를 살펴봅시다.

let numbers = [1, 2, 3, 4, 5]

print(numbers.dropFirst(2))
// Prints "[3, 4, 5]"

print(numbers.dropFirst(10))
// Prints "[]"

k를 2로 설정했으니 초기 element 2개를 제외하고 나머지를(subsequence) 리턴해주네요.

삭제할 element수가 컬렉션 개수를 초과하면 빈 subsequence를 리턴합니다.

 

빈 배열에 dropFirst()를 호출하면 어떻게 될까요?

let number = [Int]()

print(number.dropFirst())
// Prints "[]"

동일하게 빈 subsequence를 리턴합니다.

 

만약 컬렉션이 RandomAccessCollection를 준수한다면 O(1)의 복잡성을 가지고 그렇지 않다면 O(k)의 복잡성을 가지게 됩니다. 


컬렉션의 시작 부분에서 지정된 수만큼의 element를 제거합니다.

그리고 아래와 같이 선언되어 있습니다.

mutating func removeFirst(_ k: Int)

선언된 부분을 살펴보면 매개변수 k는 컬렉션에서 제거할 element 수입니다.

이는 0보다 크거나 같아야 하고 컬렉션의 개수를 초과하면 안 됩니다.

mutating키워드가 선언되어 있네요.

그리고 반환되는 것이 없네요.

 

제공된 예제를 살펴봅시다. 

var bugs = ["Aphid", "Bumblebee", "Cicada", "Damselfly", "Earwig"]
bugs.removeFirst(3)
print(bugs)
// Prints "["Damselfly", "Earwig"]"

k로 3을 설정했으니 bugs 배열의 앞 element 3개를 제거하게 됩니다.

 

이 메서드는 O(n)의 복잡성을 가집니다. 


 

여기까지 살펴본 두 메서드는 모두 배열의 인스턴스 메서드입니다. 

하지만 선언한 부분이 꽤 다른 것을 확인할 수 있었습니다.

func dropFirst(_ k: Int = 1) -> ArraySlice<Element>
mutating func removeFirst(_ k: Int)

스위프트에서 배열은 구조체로 선언되어 있습니다.

구조체 내부에서 데이터 수정이 필요한 removeFirst는 mutating키워드가 붙었고

그럴 필요가 없는 dropFirst는 mutating키워드가 붙어있지 않는 대신에 subsequence를 리턴해줍니다.

 

또 dropFirst는 k의 디폴트 값이 1인 이유는 빈 배열에 dropFirst메서드를 호출해도 빈 subsequence를 리턴해줍니다.

반면에 removeFirst는 배열 자체를 수정하기 때문에 디폴트 값이 없었습니다.

빈 배열을 호출하게 된다면 에러가 발생하게 됩니다.

Thread 1: Fatal error: Can't remove first element from an empty collection

 

resource: 

developer.apple.com/documentation/swift/array/1688675-dropfirst

developer.apple.com/documentation/swift/array/2886730-removefirst

반응형

'개발 > Swift' 카테고리의 다른 글

스위프트 오버플로우 연산  (0) 2020.09.20
스위프트 비트 연산자  (0) 2020.09.18
스위프트 Identifiable 프로토콜  (0) 2020.06.16
스위프트 클래스  (0) 2020.05.30
스위프트 인터뷰  (0) 2020.05.30