TIL 11일 차 - Swift 필수 문법 문제 3번 풀이

문제 3-1.
- Int 배열의 짝수번째 요소를 제거해서 반환하는 함수 a를 작성해 주세요.
- 테스트 입력: [1, 2, 3, 4, 5], 테스트 출력: [2, 4]
- String 배열의 짝수번째 요소를 제거해서 반환하는 함수 b를 작성해 주세요.
- 테스트 입력: [”가”, “나”, “다”, “라”, “마”], 테스트 출력: [”나”, “라”]
내가 처음으로 푼 풀이과정
// 과제3 풀이
// 3-1
func a (array: [Int]) -> [Int] {
var returnArray = [Int]()
var count: Int = 0 // count 변수 0으로 지정
for i in array {
count += 1 // 배열을 순회할때마다 count 변수에 1씩 추가
if count % 2 == 0 { // 짝수번째 배열이면 returnArray에 append하기
returnArray.append(i)
}
}
return returnArray
}
print(a(array: [1, 2, 3, 4, 5])) // [2, 4] 출력
// 3-2
// 3-1번 풀이와 매개변수의 타입만 다를뿐 풀이 방식은 같음
func b (array: [String]) -> [String] {
var returnArray = [String]()
var count: Int = 0
for i in array {
count += 1
if count % 2 == 0 {
returnArray.append(i)
}
}
return returnArray
}
print(b(array: ["가", "나", "다", "라", "마"])) // ["나", "라"] 출력
이렇게 풀었었는데 최종 과제 제출 전 금요일 마스터반 코드리뷰시간에 다른 분들은 count변수를 새로 생성하는 게 아니라
반복문을 0부터 array.count - 1만큼 돌게 하고 i를 2로 나눈 값이 1일 때(짝수번째일 때) returnArray에 i번째 배열의 값을 append 해주셨길래 나도 그런 식으로 수정해 봤다.
내가 했던 방식보다 이해가 쉽고 코드도 간결해져서 배열과 반복문의 사용에서 작성할 코드의 방식이 이번기회에 뚜렷해진 것 같다.
// 과제3 풀이 (수정)
// 3-1
func a (array: [Int]) -> [Int] {
var returnArray = [Int]()
for i in 0..<array.count - 1 { // count 변수를 별도로 내가 생성해줄필요없이 .count를 이용하면 더 가독성이 좋고 간략하게 코드를 작성할수있음
if i % 2 == 1 { // array의 짝수번째 배열이면 returnArray에 append하기
returnArray.append(array[i])
}
}
return returnArray
}
print(a(array: [1, 2, 3, 4, 5])) // [2, 4] 출력
// 3-2
// 3-1번 풀이와 매개변수의 타입만 다를뿐 풀이 방식은 같음
func b (array: [String]) -> [String] {
var returnArray = [String]()
for i in 0..<array.count - 1 {
if i % 2 == 1 {
returnArray.append(array[i])
}
}
return returnArray
}
print(b(array: ["가", "나", "다", "라", "마"])) // ["나", "라"] 출력
문제 3-2.
- 위 두 함수를 하나의 함수로 대체할 수 있는 방법을 고민해 보고, 함수 c로 작성해 주세요.
- 테스트 입력들을 넣고 호출하여 출력이 제대로 나오는지 작성해 주세요.
- 테스트 입력: [1, 2, 3, 4, 5], [”가”, “나”, “다”, “라”, “마”]
- 테스트 출력: [2, 4], [”나”, “라”]
위에서 본 두 문제는 파라미터의 타입만 다를 뿐이고 로직은 일치한다.
이 문제를 풀기 위해선 우선 제네릭에 대해 공부해야 한다.
제네릭이 없다면 [Int] 타입을 넣을 때 쓸 함수와 [String] 타입을 넣을 때 쓸 함수를 각각 정의해야 하고 코드를 수정할 때도 일일이 두 군데의 코드를 한 땀 한 땀 수정할 것이다.
튜터님께서 해주셨던 말씀 중에 '개발자들은 중복을 극도로 싫어한다'라고 말씀하셨던 게 이때 기억났다..
// 제네릭 사용
func c<T>(array: [T]) -> [T] {
var returnArray = [T]()
// 구현부는 위 코드와 일치함
}
입력타입 = 반환타입이 모두 일치하게 설정함
공부하다 보니 제네릭을 사용할 때 왜 함수이름 뒤에 <T>를 붙이는지도 궁금했다.
일단 스위프트 문법상 제네릭 타입은 함수 이름 바로 뒤에서 선언해야 한다.
그냥 일종의 펫 같은 거라고 생각하면 되겠다. 나 제네릭 쓸 거야~ 하고 함수이름 선언 후 바로 <T>로 선전포고 때리고
파라미터로는 [T] 타입을 가질 거야~라고 말하는 거라고 생각하면 될 거 같다.
마지막
문제 3-3.
- 함수 c를 기반으로 수정하여 함수 d를 작성해 주세요.
- 파라미터의 타입을 << 'Numeric 프로토콜'을 준수하는 타입의 요소를 가진 배열 >> 로 변경합니다.
일단 Numeric 프로토콜을 준수하는 타입의 요소를 가진 배열..이라는 게 무슨 뜻이냐!
쉽게 말하면 아무 타입을 원소로 가진 배열이 아니라 '숫자타입'을 원소로 가진 배열만 받겠다!라는 규칙을 세운 거다.
Numeric 프로토콜은 Swift가 미리 정해둔 프로토콜로 Int, Double, Float처럼 숫자연산이 가능한 타입들의 규칙인 것이다.
// 3-4
func d<T: Numeric>(array: [T]) ->[T] {
// 원소 T에 Numeric 프로토콜 제약조건 설정
var returnArray = [T]()
for i in 0..<array.count-1 {
if i % 2 == 1 {
returnArray.append(array[i])
}
}
return returnArray
}
print(d(array: [1, 2, 3, 4, 5])) // [2, 4] 출력
// Numeric 프로토콜을 준수하는 타입만을 받는 함수이므로
//print(d(array: ["가", "나", "다", "라", "마"])) 오류 발생
그래서 제네릭을 사용해서 타입을 상황에 따라 바뀌도록 유동적으로 설정할 수 있지만,
프로토콜 제약조건을 설정해서 제네릭에 사용할 수 있는 타입의 범위를 적절히 제한해 코드의 의도를 명확히 할 수 있다는 것이 이 문제의 출제 의도인 것 같다.
'iOS > Swift ' 카테고리의 다른 글
| [iOS- Swift] 스위프트 필수 문법 문제 5번 풀이 (0) | 2026.01.10 |
|---|---|
| [iOS-Swift] 스위프트 필수 문법 문제 4번 풀이 (0) | 2026.01.10 |
| [iOS- Swift] 스위프트 필수 문법 문제 2번 풀이 (0) | 2026.01.09 |
| [iOS-Swift] 스위프트 필수 문법 문제 1번 풀이 (0) | 2026.01.09 |
| [iOS-Swift] 타입캐스팅 (0) | 2026.01.09 |