假设有一个需求,需要根据两个数组的内容生成一个对象数组。比如下面的代码:
let ages = [21, 20, 23, 24]
let names = ["张三", "李四", "王二", "赵六"]
struct Student {
var name: String
var age: Int
}
现有 ages 和 names 两个数组,我们需要根据这两个数组的内容生成一个包含 Student 对象的数组。
map ?
如果是一个数组把它映射成对象数组的话,用 map 是最合适的,比如下面的代码:
struct Student {
var name: String
}
let names = ["张三", "李四", "王二", "赵六"]
let stus = names.map { Student(name: $0) }
但我们需要将 ages 和 names 的值都添加到 Student 对象中,而 map 函数并没有提供 index 的参数,所以 map 无法实现上述的需求。
zip ?
因为我们需要同时用到两个数组同一位置的元素,所以也可能回想到它。比如下面的代码:
let stuSeq = zip(ages, names)
var stus = [Student]()
for (age, name) in stuSeq {
stus.append(Student(name: name, age: age))
}
虽然上面的代码也可以实现需求,但是代码不够 Swift,Swift 官方是推荐我们更多的使用高阶函数,尽可能的少用 for-in 等循环语句,原因是高阶函数更易读、易维护。
map + zip ✔️
通过上面的尝试可以发现,map 和 zip 单独使用要么不能实现需求,要么代码不够优雅,那么它们组合起来使用呢?
下面就是终极版本:
// 先构造 Zip2Sequence
let stuSeq = zip(ages, names)
// 再去映射
let stus = stuSeq.map { (age, name) -> Student in
return Student(name: name, age: age)
}
这样我们即实现了需求,也因为使用了 map 函数而可以将 stus 声明为 let(zip 因为要添加元素所以不能将 stus 声明为 let),从而使代码易读、健壮。
希望读完这篇文章,大家能有一些收获。对于这种需求小伙伴们有没有更好的解决方案呢?欢迎在评论区留言。