Swift/Swift 기본문법

Swift 기본 문법 - 16. 맵,필터,리듀서

728x90

16. 맵, 필터, 리듀서

고차함수라 불리는 애들이다.

 

16.1 맵

맵은 collection의 값을 변경하기위해 주로 사용됩니다.

신기 했던 부분은 dictionary 컬렉션은 map으로 돌리면 내부는 튜플로 받아와지는점이 당황스러웠습니다.

반환 값은 배열로 반환해줍니다.

let numbers: [Int] = [0, 1, 2, 3, 4]

var doubleNumbers: [Int] = [Int]()

doubleNumbers = numbers.map({ (number: Int) -> Int in
                                return number * 2 })

doubleNumbers = numbers.map({ $0 * 2 })

print(doubleNumbers)



let alphabetDictionary: [String: String] = ["a":"A", "b":"B"]

// 튜플로 map의 전달인자로 받는다.
var keys: [String] = alphabetDictionary.map { (tuple: (String, String)) -> String in
    return tuple.0
}


keys = alphabetDictionary.map{$0.0}
let values: [String] = alphabetDictionary.map{$0.1}

print(keys)
print(values)

 

16.2 필터

필터는 말 그대로 컨테이너 내부의 값을 걸러서 추출하는 역할의 고차함수입니다.

매개변수로 전달되는 함수의 반환 타입은 Bool 입니다. 반환 값이 true인 값들만 골라서 추출할 수 있습니다.

let numbers: [Int] = [0, 1, 2, 3, 4, 5]

let evenNumbers: [Int] = numbers.filter{ (number: Int) -> Bool in
    return number % 2 == 0
}

print(evenNumbers)

let oddNumbers: [Int] = numbers.filter{$0 % 2 == 1}

print(oddNumbers)


// map 과 filter가 체인처럼 연결하여 사용 할 수 있습니다.
let chainNumbers: [Int] = numbers.map{$0 + 3}.filter{$0 % 2 == 1}
print(chainNumbers)

 

16.3 리듀스

리듀스는 내부의 콘텐츠를 하나로 합하는 기능을 실행하는 고차함수입니다.

배열이라면 배열의 모든 값을 전달인자로 전달받은 클로저의 연산 결과로 합해줍니다.

리듀스의 첫번째 매개변수는 초깃 값을 지정해 줄 수 있으며, 다음 매개변수는 클로저를 받습니다.

let numbers: [Int] = [1, 2, 3]

var sum: Int = numbers.reduce(0, { (result: Int, next: Int) -> Int in
    print("\(result) + \(next)")
    return result + next
})

print(sum)

// 초깃값이 0이고 정수 배열의 모든 값을 뺍니다.
let subtract: Int = numbers.reduce(0, { (result: Int, next: Int) -> Int in
    print("\(result) - \(next)")
    return result - next
})

print(subtract)

// 후행 클로저, 트레일링 클로저
// 초깃 값이 3이고 모든 값을 더합니다.
var sumFromThree: Int = numbers.reduce(3){$0 + $1}
print(sumFromThree)

// 문자열 배열을 reudce메서드를 이용해 연결
let names: [String] = ["Chope", "Jay", "Joker", "Nova"]

let reducedNames: String = names.reduce("kemi's friend : ") {
    return $0 + $1 + ", "
}
print(reducedNames)


// 클로저에 Return 값이 없을 때
// 내부에서 직접 이전 값을 변경함.
sum = numbers.reduce(into: 0, { (result: inout Int, next: Int ) in
    print("\(result) + \(next)")
    result += next
})

print(sum)  //6

var subtractFromThree: Int = numbers.reduce(into: 3, {
    print("\($0) - \($1)")
    $0 -= $1
})
print(subtractFromThree)

// 초깃값을 배열로 전달 할 수 도 있습니다.
// inout을 통해 참조변수를 만들어서 return값 없이 처리 할 수 있습니다.
var doubledNumbers: [Int] = numbers.reduce(into: [1,2,3], { (result: inout [Int], next: Int) in
    print("result: \(result) next: \(next)")
    

    guard next != nil else {
        return
    }
    
    print("\(result) append \(next)")
    
    result.append(next * 2)
})

print(doubledNumbers)

 

맵, 필터, 리듀스 메서드의 연계 사용 

// 맵,필터, 리듀서 연계사용

let numbers: [Int] = [1, 2, 3, 4, 5, 6, 7]

// 짝수를 걸러내어 각 값에 3을 곱해준 후 모든 값을 더합니다.
var result: Int = numbers.filter{$0.isMultiple(of: 2)}.map{$0 * 3}.reduce(into: 0){$0 += $1}

print(result)


// 맵 필터 리듀스의 활용

enum Gender {
    case male, female, unknown
}

struct Friend {
    let name: String
    let gender: Gender
    let location: String
    var age: UInt
}

var friends: [Friend] = [Friend]()
friends.append(Friend(name: "Yoobato", gender: .male, location: "발리", age: 26))
friends.append(Friend(name: "Jinso", gender: .male, location: "시드니", age: 24))
friends.append(Friend(name: "JiYoung", gender: .female, location: "서울", age: 22))

// 서울 외의 지역에 거주하며 25세 이상인 ㅊ니구
var resultFriend: [Friend] = friends.map{Friend(name: $0.name, gender: $0.gender, location: $0.location, age: $0.age + 1 )}

resultFriend = resultFriend.filter{ $0.location != "서울" && $0.age >= 25 }

let string: String = resultFriend.reduce("서울 외의 지역에 거주하며 25세 이상인 친구") {$0 + "\n" + "\($1.name)" + "\($1.gender)" + " \($1.location)" + " \($1.age)세"}

print(string)

// 서울 외의 지역에 거주하며 25세 이상인 친구
// Yoobatomale 발리 27세
// Jinsomale 시드니 25세

 

반응형