Swift 코딩테스트와 개발 시 유용하게 사용할 수 있는 고차 함수 및 메서드를 키워드와 함께 정리해보자. 사전처럼 참고하여 각 메서드의 기능을 알고 적절히 활용할 수 있을지도?
map: 배열의 각 요소를 변형하여 새로운 배열로 반환함.
 let numbers = [1, 2, 3]
 let doubled = numbers.map { $0 * 2 } // [2, 4, 6]
filter: 특정 조건을 만족하는 요소들만 필터링하여 새로운 배열로 반환함.
let evenNumbers = numbers.filter { $0 % 2 == 0 } // [2]
reduce: 배열의 모든 요소를 하나의 값으로 축약함.
let sum = numbers.reduce(0) { $0 + $1 } // 6
compactMap: nil 값을 제외하고 변환하여 새로운 배열로 반환함.
let strings = ["1", "2", "a"]
let validNumbers = strings.compactMap { Int($0) } // [1, 2]
flatMap: 중첩된 배열을 평탄화하여 하나의 배열로 반환함.
let nestedArray = [[1, 2], [3, 4]]
let flattened = nestedArray.flatMap { $0 } // [1, 2, 3, 4]
allSatisfy: 배열의 모든 요소가 특정 조건을 만족하는지 확인함.
let allPositive = numbers.allSatisfy { $0 > 0 } // true
contains(where:): 배열의 요소 중 특정 조건을 만족하는 요소가 있는지 확인함.
let hasEven = numbers.contains { $0 % 2 == 0 } // true
forEach: 배열의 각 요소에 대해 주어진 클로저를 실행함.
numbers.forEach { print($0) } // 1, 2, 3 출력
sorted(by:): 배열의 요소를 지정된 기준으로 정렬함.
let sortedNumbers = numbers.sorted(by: >) // [3, 2, 1]
firstIndex(of:): 배열에서 특정 요소의 첫 번째 인덱스를 반환함.
let index = numbers.firstIndex(of: 2) // 1
contains: 배열에 특정 요소가 포함되어 있는지 확인함.
let hasThree = numbers.contains(3) // true
split(separator:): 문자열을 특정 구분자로 나누어 배열로 반환함.
let sentence = "Hello World"
let words = sentence.split(separator: " ") // ["Hello", "World"]
joined(separator:): 문자열 배열을 하나의 문자열로 합침.
let joinedString = words.joined(separator: " ") // "Hello World"
max() / min(): 배열의 최대값 또는 최소값을 찾음.
let maxValue = numbers.max() // 3
let minValue = numbers.min() // 1
reversed(): 배열의 요소를 역순으로 변환하여 반환함.
let reversedNumbers = numbers.reversed() // [3, 2, 1]
enumerated(): 배열의 인덱스와 값을 동시에 반복하고자 할 때 사용함.
for (index, value) in numbers.enumerated() {
    print("\(index): \(value)")
}
// 0: 1, 1: 2, 2: 3
prefix(_:) / suffix(_:): 배열의 처음 n개의 요소 또는 마지막 n개의 요소를 반환함.
let firstTwo = numbers.prefix(2) // [1, 2]
let lastTwo = numbers.suffix(2)  // [2, 3]
dropFirst(_:) / dropLast(_:): 배열에서 처음 또는 마지막 n개의 요소를 제외한 나머지를 반환함.
let droppedFirst = numbers.dropFirst(1) // [2, 3]
let droppedLast = numbers.dropLast(1)   // [1, 2]
chunked(into:) (Swift 5.8+): 배열을 특정 크기 단위로 나누고 싶을 때 사용함.
let chunks = numbers.chunked(into: 2) // [[1, 2], [3]]
zip(_:_:): 두 배열을 병합하여 튜플 형태의 배열을 만듦.
let names = ["Alice", "Bob"]
let scores = [90, 85]
let paired = zip(names, scores) // [("Alice", 90), ("Bob", 85)]
stride(from:to:by:): 특정 범위에서 간격을 설정하여 반복하는 방법임.
for value in stride(from: 0, to: 10, by: 2) {
    print(value) // 0, 2, 4, 6, 8
}
Set 사용한 중복 제거: 배열에서 중복된 요소를 제거하고 고유한 값들만 남김.
let duplicates = [1, 2, 2, 3]
let uniqueElements = Array(Set(duplicates)) // [1, 2, 3]
append(_:) / removeLast(): 배열을 스택처럼 사용하기 위한 메서드. 요소를 추가하고 제거함.
var stack = [1, 2, 3]
stack.append(4)      // [1, 2, 3, 4]
let lastElement = stack.removeLast() // 4
removeFirst(): 큐에서 첫 번째 요소를 제거하기 위한 메서드.
var queue = [1, 2, 3]
let firstElement = queue.removeFirst() // 1
permutations (직접 구현 필요): 특정 배열의 모든 순열을 계산할 때 자주 구현해야 함.
func permutations<T>(_ array: [T]) -> [[T]] {
    if array.count == 0 { return [[]] }
    return array.indices.flatMap { i -> [[T]] in
        var remainder = array
        let element = remainder.remove(at: i)
        return permutations(remainder).map { [element] + $0 }
    }
}
combinations (직접 구현 필요): 조합을 계산할 때 자주 구현해야 함.
func combinations<T>(_ array: [T], _ count: Int) -> [[T]] {
    guard count > 0 else { return [[]] }
    guard count <= array.count else { return [] }
    if count == array.count { return [array] }
    var result = combinations(Array(array.dropFirst()), count)
    let partial = combinations(Array(array.dropFirst()), count - 1)
    result += partial.map { [array.first!] + $0 }
    return result
}
함수 설계 시 유의사항:
calculateSum()처럼 명확하게 어떤 작업을 하는지 알 수 있도록 작성.조건문 작성 시 유의사항:
if let이나 guard let을 사용해 옵셔널 값을 안전하게 언래핑하는 것이 중요함.? :)를 사용하여 코드의 길이를 줄일 수 있음. 예: let result = condition ? trueValue : falseValue.&&와 ||를 활용해 여러 조건을 결합할 때, 괄호를 사용해 가독성을 높이는 것이 좋음.