티스토리 뷰
안녕하세요 :) Zedd입니다.
Array의 인스턴스 메소드로 prefix / suffix가 있잖아요!?
다같은 prefix / suffix가 아니고..파라미터에 따라 조금씩 다른데,
그냥 썼다가 아주 큰일날뻔 했어서 ㅎㅎ.. 한번 쫙 살펴보려고 합니다.
# 들어가기전에
prefix / suffix 친구들은 Array의 인스턴스 메소드이지만, return 타입은 ArraySlice<Element> 입니다.
func someMethod(_ arr: [Int]) {}
let arr = [1, 2, 3, 4].prefix(3)
someMethod(arr) // 🚨 Error!
[Int]의 prefix를 가져왔지만, [Int]가 나오지 않고 ArraySlice<Int>가 나왔기 때문에 위 코드는 컴파일 에러가 나게 됩니다.
func someMethod(_ arr: [Int]) {}
let arr = [1, 2, 3, 4].prefix(3)
someMethod(Array(arr)) // ✅
그래서 이렇게 Array로 한번 더 감싸주든가 해서 넘겨야합니다.
[prefix]
prefix메소드는 4가지 종류가 있습니다.
prefix(_ maxLength: Int)
prefix(upTo end: Int)
prefix(through position: Int)
prefix(while predicate: (Element) -> Bool)
# prefix(_ maxLength: Int)
Collection에서 지정한 maxLength까지 하위 시퀀스를 리턴합니다.
(maxLength는 0 이상이어야함)
let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(2))
// Prints "[1, 2]"
print(numbers.prefix(10))
// Prints "[1, 2, 3, 4, 5]"
array의 요소는 5개까지 밖에 없지만, 내가 prefix(10)을 한다고 해서 에러가 나는건 아닙니다.
그래서 내가 배열의 prefix를 가져오고 싶다~ 하는 거의 모든 케이스는 이 메소드로 커버가 될거에요 ㅎㅎ
# prefix(upTo: Int)
upTo하면 보통 ~~까지라는 뜻이잖아요?
prefix(upTo: Int)는 Collection의 시작부터 지정된 위치까지(포함하지 않음)의 하위 시퀀스를 반환합니다.
자 여기서부터 살짝 헷갈릴 수 있는데요.
prefix(_ maxLength: Int)에서는 그냥 앞에 maxLength개 내놔!! 이런식이었다면..
prefix(upTo: Int)는 이 Argument가 Index를 의미한다고 보면 됩니다.
let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(upTo: 4))
자 이렇게 하면 numbers의 인덱스는 0, 1, 2, 3, 4입니다.
어 근데 내가 prefix(upTo: 4)를 요청했어.
그럼 Collection의 시작부터 지정된 위치(포함하지 않음)의 하위시퀀스가 반환됩니다.
그러니까
[인덱스 - Value]
0 - 1
1 - 2
2 - 3
3 - 4
--
4 - 5 < 포함하지 않음!
이렇게 되는거죠.
그래서 결과는
let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(upTo: 4))
// [1, 2, 3, 4]
가 나오게 됩니다. 그냥 Index로 생각하시면 편합니다.
upTo네? 포함안하니까 4번째 Index 전까지? 4번째 Index가 5니까..5전까지 리턴되겠네..[1, 2, 3, 4]네..
아직도 이해가 안간다면 아래 예제를 봅시다.
let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(upTo: numbers.startIndex))
// []
startIndex..즉 0일텐데, 시작(==Index 0) 부터 Index 0까지인데!!포함안해
그러니까 빈 배열([])이 나오는거죠.
🚨 주의사항 🚨
아래 코드를 보겠습니다.
let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(upTo: 10))
print(numbers.prefix(10))
하나는 upTo고 하나는 그냥 prefix네요.
위 코드는 prefix(upTo:) 메소드때문에 crash를 발생시킵니다.
Array index is out of range
이기 때문에..
10번째 Index 전까지 가져와야하는데, 해당 Index가 없으니 Array index is out of range 가 나는 것입니다!!!!
이거 때문에 살짝 큰일날뻔...ㅎ
그러니까 prefix(upTo:)를 사용할 땐 항상 주의하기!!!!!!
🔖 참고
prefix(upTo:)를 사용하는것은 subscript notation을 아래와 같이 사용하는 것과 동일합니다.
let numbers = [1, 2, 3, 4, 5]
print(numbers[..<4])
// [1, 2, 3, 4]
prefix(upTo:)이렇게 사용하는 것 보다 subscript notation이 더 선호되는 표기법이라고 해요.
(The subscript notation is preferred over prefix(upTo:))
# prefix(through: Int)
stride에도 through가 있으니...잘 아시겠지만, upTo는 Argument를 포함안했다면 through는 포함합니다.
let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(through: 4))
// [1, 2, 3, 4, 5]
[인덱스 - Value]
0 - 1
1 - 2
2 - 3
3 - 4
4 - 5
upTo는 4로 넘기면 4번째 인덱스 전까지! 그러니까 [1, 2, 3, 4] 이렇게 나왔다면,
through는 포함하기 때문에 [1, 2, 3, 4, 5]가 나오게 됩니다.
let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(through: numbers.startIndex))
// [1]
바로 알겠죠!?
upTo와 똑같이 Index로 접근하기 때문에
let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(through: 10)) // 🚨 Fatal error: Array index is out of range
print(numbers.prefix(10))
반드시 Valid한 Index를 넣어야합니다.
# prefix(while predicate: (Element) -> Bool)
다른 prefix는 그냥 숫자만 넣어주면 됐다면..이건 Closure가 있네요.
간단합니다.
요소를 포함해야하는 경우 - true
요소를 제외해야하는 경우 - false
predicate가 false를 반환하면 다시 호출되지 않음.
만 기억하면 됩니다.
예제로 봅시다.
let numbers = [3, 1, 2, 5, 4]
print(numbers.prefix(while: { $0 >= 3 }))
// [3]
3보다 같거나 큰 수들에 대해 prefix를 호출했습니다.
첫번째 element의 3은 3보다 같거나 크니 true
두번째 element의 1은 3보다 작으므로 false
predicate가 false를 리턴했으므로 종료.
결과 : [3]
쉽죠..!?
[suffix]
suffix메소드는 2가지 종류가 있습니다.
suffix(_ maxLength: Int)
suffix(from start: Int)
# suffix(_ maxLength: Int)
prefix(_ maxLength:)와 완전히 똑같습니다.
(maxLength는 0이상 이어야 합니다.)
let numbers = [1, 2, 3, 4, 5]
print(numbers.suffix(2))
// Prints "[4, 5]"
print(numbers.suffix(10))
// Prints "[1, 2, 3, 4, 5]"
# suffix(from start: Int)
요것도 Index기반이라고 생각하면 됩니다.
내가 start로 넘긴 지정된 위치에서 Collection 끝까지의 하위 시퀀스를 반환합니다.
let numbers = [1, 2, 3, 4, 5]
print(numbers.suffix(from: 3))
// [4, 5]
from: 3..그러니까 Index 3부터 Collection의 끝(== Index 4)을 리턴하니
[4, 5]가 리턴되는거죠. (~부터니까 시작은 포함하면 됩니다.)
🚨 주의 사항🚨
Index기반이기 때문에 역시나 반드시 Valid한 Index를 넣어줘야합니다.
let numbers = [1, 2, 3, 4, 5]
print(numbers.suffix(from: 6)) // 🚨 Fatal error: Range requires lowerBound <= upperBound
위와같은 에러가 나온 이유는 대충 짐작이 가시죠!?
from: 6.. 그러니까 Index 6부터 Collection의 끝(== Index 4)을 리턴해야하는데
Range가 [6...4] == lowerBound가 upperBound보다 큰 상황이니 에러를 내게 됩니다.
suffix(from start: Int) 역시 subscript notation을 더 선호하는데요.
let numbers = [1, 2, 3, 4, 5]
print(numbers[3...])
// [4, 5]
suffix(from: 3)이라고 표기하는 것 보다 numbers[3...]이렇게 표기하는걸 더 선호한다는 거!
'Swift' 카테고리의 다른 글
Swift ) Sequence (1) | 2022.02.05 |
---|---|
Literal (0) | 2022.01.23 |
Swift 5.5 ) Codable synthesis for enums with associated values (0) | 2021.11.18 |
WWDC 21 ) What‘s new in Swift (3) | 2021.06.11 |
Swift 5.4 Released! (3) | 2021.04.28 |
- Combine
- FLUTTER
- Accessibility
- 스위프트
- WKWebView
- IOS
- SwiftUI
- WidgetKit
- swift delegate
- ios 13
- np-complete
- 회고
- 제이슨 파싱
- 스위프트 문법
- swift tutorial
- Swift
- actor
- swift 공부
- np-hard
- fastlane
- Git
- 피아노
- swift array
- Xcode
- github
- swift3
- UIBezierPath
- iOS delegate
- swift sort
- WWDC
- Total
- Today
- Yesterday