
import Foundation
func solution(_ arr:[Int], _ queries:[[Int]]) -> [Int] {
var result = arr
for query in queries {
let (s, e, k) = (query[0], query[1], query[2])
for idx in s...e {
result[idx] = idx % k == 0 ? result[idx] + 1 : result[idx]
}
}
return result
}
import Foundation
func solution(_ arr:[Int], _ queries:[[Int]]) -> [Int] {
return queries.reduce(into: arr) { arr, query in
(query[0]...query[1]).filter { $0 % query[2] == 0 }.forEach { arr[$0] += 1 }
}
}
queries.reduce(into: arr) { arr, query in ... }
reduce(into:): 초기값(arr)을 시작으로 컬렉션의 각 요소에 대해 누적 작업을 수행into: arr: 초기값으로 arr 배열의 복사본을 사용하고, 이를 직접 수정함arr: 현재까지의 누적 결과 배열 (mutable)query: 현재 처리 중인 쿼리 정보💡 reduce 함수를 축약형으로 사용하지 못하는 이유
reduce 함수 축약형은 주로 다음과 같은 경우에 사용한다.
- 연산이 단일 연산자(
+,*등)로 표현 가능- 복잡한 조건문이나 다른 함수 호출이 없음
- 누적값과 요소 모두 동일한 방식으로 처리됨
reduce(into:)는 일반 reduce와 달리 다음과 같은 특성이 있다.
- 누적값이 mutable로 처리됨 (직접 수정 가능)
- 각 단계에서 반환값 필요 없음
- 내부에서 컬렉션 조작이 자주 이루어짐
→ 복잡한 작업의 경우reduce(into:)사용
(query[0]...query[1]).filter { $0 % query[2] == 0 }
query[0]...query[1]: s부터 e까지의 인덱스 범위를 생성.filter { $0 % query[2] == 0 }: 범위 내에서 k(query[2])의 배수인 인덱스만 선택.forEach { arr[$0] += 1 }
forEach: 선택된 각 인덱스에 대해 작업 수행→ 첫 풀이에서의 고민 해결!
💡 forEach 함수의 특징
- 반환 값이 없음:
forEach는Void를 반환한다. 즉, 결과를 모으거나 변환된 컬렉션을 반환하지 않는다.- 원본 변경 없음: 원본 컬렉션을 변경하지 않는다.
- 순서 보장: 배열과 같은 순서가 있는 컬렉션에서는 요소를 순서대로 처리한다.
break/continue사용 불가return의 동작: 클로저 내에서return을 사용하면 현재 요소의 처리만 종료하고 다음 요소로 진행한다 (전체 반복 종료 안 됨).
forEach 함수를 새롭게 알았다. method chaining을 통해 더 간결한 코드를 사용할 수 있을 것 같다.
reduce 함수는 축약형으로만 사용해오다 보니, 기본형을 사용할 생각은 못했다. 복잡한 처리가 필요한 경우에도 사용할 수 있구나 깨달았다.