# Swift高阶函数使用技巧与部分场景 (`reduce`等)

### 前言

let students = [
Student(id: "991", name: "Jessica", gender: .female, age: 20),
Student(id: "992", name: "James", gender: .male, age: 25),
Student(id: "993", name: "Mary", gender: .female, age: 19),
Student(id: "994", name: "Edwin", gender: .male, age: 27),
Student(id: "995", name: "Stacy", gender: .female, age: 18),
Student(id: "996", name: "Emma", gender: .female, age: 22),
]

enum Gender {
case male
case female
}

struct Student {
let id: String
let name: String
let gender: Gender
let age: Int
}

## 计算数组元素的出现次数

let genderCount = students.reduce(into: [Gender: Int]()) { result, student in

guard var count = result[student.gender] else {
// Set initial value to `result`
result[student.gender] = 1
return
}

// Increase counter by 1
count += 1
result[student.gender] = count
}

let femaleCount = genderCount[.female]! // Output: 4
let maleCount = genderCount[.male]!     // Output: 2

#### 复习Swiftreduce 函数

result: 一般是指上次得到的结果之和

currentCase: 一般指本次遍历的对象

let prices = [20,30,40]
let sum = prices.reduce(0) { \$0 + \$1 }
print(sum)

//90

[Gender: Int]() : 是一个以 GenderKey, int的的字典

▿ 2 elements
▿ 0 : 2 elements
- key : SwiftUnitTest.Gender.female
- value : 4
▿ 1 : 2 elements
- key : SwiftUnitTest.Gender.male
- value : 2

## 获取数组内某个model属性的总和

let sum = students.reduce(0) { result, student in
return result + student.age
}

let sum = students.reduce(0, { \$0 + \$1.age })

let sum1 = [2, 3, 4].reduce(0, +)          // Output: 9
let sum2 = [5.5, 10.7, 9.43].reduce(0, +)  // Output: 44.435
let sum3 = ["a","b","c"].reduce("", +)     // Output: "abc"

reduce 是很好用的,在计算数值,和拼接字符串的时候.

## 从数组中获取一些随机元素

// Randomize all elements within the array
let randomized = students.shuffled()

// Get the first 3 elements in the array
let selected = randomized.prefix(3)
let selected2 = randomized.prefix(13)
print(selected)
print(selected2)

[SwiftUnitTest.Student(id: "996", name: "Emma", gender: SwiftUnitTest.Gender.female, age: 22),
SwiftUnitTest.Student(id: "991", name: "Jessica", gender: SwiftUnitTest.Gender.female, age: 20),
SwiftUnitTest.Student(id: "992", name: "James", gender: SwiftUnitTest.Gender.male, age: 25)]

[SwiftUnitTest.Student(id: "996", name: "Emma", gender: SwiftUnitTest.Gender.female, age: 22),
SwiftUnitTest.Student(id: "991", name: "Jessica", gender: SwiftUnitTest.Gender.female, age: 20),
SwiftUnitTest.Student(id: "992", name: "James", gender: SwiftUnitTest.Gender.male, age: 25),
SwiftUnitTest.Student(id: "995", name: "Stacy", gender: SwiftUnitTest.Gender.female, age: 18),
SwiftUnitTest.Student(id: "993", name: "Mary", gender: SwiftUnitTest.Gender.female, age: 19),
SwiftUnitTest.Student(id: "994", name: "Edwin", gender: SwiftUnitTest.Gender.male, age: 27)]

## 按条件对数组元素进行分组

struct Student {
let id: String
let name: String
let gender: Gender
let age: Int
}

let groupByFirstLetter = Dictionary(grouping: students) { student in
return student.name.first!
}

/*
PrintLog:
[
["J": [SwiftUnitTest.Student(id: "991", name: "Jessica", gender: SwiftUnitTest.Gender.female, age: 20), SwiftUnitTest.Student(id: "992", name: "James", gender: SwiftUnitTest.Gender.male, age: 25)],
"M": [SwiftUnitTest.Student(id: "993", name: "Mary", gender: SwiftUnitTest.Gender.female, age: 19)],
"E": [SwiftUnitTest.Student(id: "994", name: "Edwin", gender: SwiftUnitTest.Gender.male, age: 27), SwiftUnitTest.Student(id: "996", name: "Emma", gender: SwiftUnitTest.Gender.female, age: 22)],
"S": [SwiftUnitTest.Student(id: "995", name: "Stacy", gender: SwiftUnitTest.Gender.female, age: 18)]]

]
*/

// Using shorthand argument names
let groupByFirstLetter = Dictionary(grouping: students, by: { \$0.name.first! })

// Using key path syntax
let groupByFirstLetter = Dictionary(grouping: students, by: \.name.first!)

iOS