“This is the third day of my participation in the First Challenge 2022, for more details: First Challenge 2022”.
In our daily development, we often encounter some complex data operation requirements. These complex requirements can take us half a day or even a few days to trend the line.
But if we can make use of the higher-order functions provided by Swift itself, we can not only reduce the complexity of the project, but also make the code more readable and efficient.
If you are not familiar with the use of higher-order functions for Swift, I recommend reading my previous article on the use of higher-order functions.
In this article, we introduce five complex data manipulation requirements that are simplified through higher-order functions. Let ‘s go!
Prepare
Suppose we have a Person structure like this:
struct Person {
enum Gender {
case male
case female
}
var name = ""
var age = 0
var gender = Gender.female
}
Copy the code
Here is the data source we need to operate on, where the following requirements operate:
Let dataSource = [Person(name: "大 吉 大宝", age: 38, gender:. Male), Person(name:" 大 吉 大宝", age: 50, gender: .female), Person(name: "coke ", age: 10, gender:. Female), Person(name:" five six seven ", age: 16, gender:. Male), Person(name: "Thirteen of plum blossom ", age: 20, gender:.female)]Copy the code
Get how many men and women are in the data source
If higher-order functions are not applicable, we might go as follows:
- Create two variables maleCount/femaleCount to represent the number of men and women.
- Loop through the elements and add if-else statements to the for-loop, maleCount +1 if male, femaleCount +1 if male.
The code above, while not too complicated to write, has two minor flaws:
- The code doesn’t know at a glance what the code actually does.
- MaleCount /femaleCount must be declared as var, but we do not need to change these two variables in the future. However, limited to the following variable modification, can only be declared as var, which will bring uncontrollable program.
This requirement can be achieved using reduce(into:) of higher-order functions:
let genderCount = dataSource.reduce(into: [Person.Gender: Int]()) { (result, person) in
result[person.gender, default: 0] += 1
}
let maleCount = genderCount[Person.Gender.male] // 2
let femaleCount = genderCount[Person.Gender.female] // 3
Copy the code
Generate a [Gender: Int] dictionary through reduce(into:) function to count male and female inside reduce.
This is also a good solution to the above two problems. Very readable code; MaleCount and femaleCount are also declared as lets.
Get two elements at random
For this requirement, we can break it down into the following two steps:
- Generate a random number group – randomDataSource through the data source.
- Get the first two elements of a randomDataSource.
The conversion code is as follows:
let randomDataSource = dataSource.shuffled()
let randomElement = randomDataSource.prefix(2)
Copy the code
Find a specific element
In project development, we often encounter the need to find a particular element in an array. If the target array has a small number of elements, for-loop or filter is most convenient. However, if the target array is large and we often need to do lookups, this implementation is not sufficient.
At this time, we can use the idea of space for time to solve the problem of long search time. The main steps are divided into the following two steps:
- Now turn the data source into an array of tuples – personTuple. The position 0 is key and the position 1 is the Person object.
- Through Dictionary’s initialization function:
init<S>(uniqueKeysWithValues keysAndValues: S)
Turn personTuple into a dictionary.
In this case, it’s order (1) time to go through the key again. Note that the process of converting an array into a dictionary is still O(n).
let personTuple = dataSource.map { ($0.name, $0)} let personDict = Dictionary(uniqueKeysWithValues: PersonTuple) let target = personDict[" five six "]Copy the code