美文网首页
Swift函数式编程

Swift函数式编程

作者: NapoleonY | 来源:发表于2018-08-09 19:37 被阅读18次

楔子

问题:给定一个数组,找出里面所有的偶数

  • 最先想到的方法是遍历数组,找出所有的偶数
  • 如果用函数式编程,可以用如下代码解决
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let events = numbers.filter { (num : Int) -> Bool in
    return num % 2 == 0
}
  • 方法解析
    • filter接受一个闭包
    • 闭包本身有一个参数,表示数组中的元素
    • 返回值是一个Bool类型,用于过滤符合条件的元素
    • 当满足条件时,就会将满足条件的元素放到数组中
  • 优点:如果是找出奇数、3的倍数等等,只需改变下闭包中的表达式即可

面向对象与函数式编程

面向对象
现在要对一个数组进行处理,我可以封装一个工具类,类中可以提供如下方法:

  • 获取数组中的偶数
  • 对数组中的元素进行排序
  • 其它各种能想得到的方法
    但是,不能考虑到所有的情况。其实,要对数组进行怎样的处理,调用者最清楚。如果能让调用者将对数组处理的操作传过来就完美了

函数式编程
Array为例,如果系统没有提供filter函数,我们可以自己扩展一个类似的函数

  • 函数的参数一个对数组中元素的操作
  • 既然是操作,操作本身也就是一个函数
  • 操作的参数是数组中的一个元素
extension Array {
    func personlFilter(oprationFunc : (Int) -> Bool) -> [Int] {
        var tempArray = [Int]()
        
        for item in self {
            if oprationFunc(item as! Int) {
                tempArray.append(item as! Int)
            }
        }
        return tempArray
    }
}
// 使用
let newEvents = numbers.personlFilter { (num) -> Bool in
            return num % 3 == 0
        }

如果想让代码更通用,我们还可以使用范型,例如获取字符串数组中包含a的字符串

reduce

reduce是函数式编程中一个常用的函数,它的作用是将集合中的元素按照某种方式合并,合并的规则由调用者决定,代码如下

let totoal = numbers.reduce(5) { (num1 : Int, num2 : Int) -> Int in
            return num1 + num2
        }

上述代码是将numbers数组中的元素求和。reduce接收两个参数

  • 参数一是合并前的初始化的值
  • 参数二是一个闭包,闭包中的第一个参数是每次合并后的值,第二个参数是下一次要合并的值

map

map可以对数组中的每一个元素做一次处理。代码如下

let animals = ["Dragon", "Cat", "Tiger", "fdakjfdakf", ""]
        
let animalCount = animals.map { (str : String) -> Int in
    let length = str.count
    return length
}
// [Optional(6), Optional(3), Optional(5), Optional(10), nil]
map巧用示例

根据已知数组,创建一个count相同的对应的数组

let titles = ["头条", "视频", "娱乐", "要问", "体育" , "科技" , "汽车" , "时尚" , "图片" , "游戏" , "房产"]

// 创建每一页对应的controller
let childViewControllers: [ContentViewController] = titles.map { _ -> ContentViewController in
    let controller = ContentViewController()
    controller.view.backgroundColor = UIColor.randomColor
    return controller
}

compactMap

Swift 4.1后,compactMap代替了flatMap,它们与map类似,但compactMap会自动剔除返回数组中的nil,并把Optional解包

let animalFlapCount = animals.compactMap { (str: String) -> Int? in
            let length = str.count
            guard length > 0 else {
                return nil
            }
            return length
        }
//[6, 3, 5, 10]

可以看出,与map返回的结果相比,少了nil

示例

实现一个函数:求0~100(包括0和100)中为偶数并且恰好是其它数字平方的数字

  1. 通常的解法
func evenSquare(from a: Int, to b: Int) ->[Int] {
        var result = [Int]()
        
        for num in a...b where ((num % 2) == 0) {
            if (a...b).contains(num * num) {
                result.append(num * num)
            }
        }
        
        return result
    }
  1. 使用函数式编程的解法
func evenSquare(from :Int, to : Int) -> [Int] {
        /*let res = [Int]()
        let res = (from...to).map { (num) -> Int in
            return num*num
            }.filter { (num) -> Bool in
                return num % 2 == 0
        }*/
        let res = (from...to).map{ $0 * $0}.filter{ $0 % 2 == 0}

        return res
    }
  • 首先使用map将将0~10映射成对应的平方数
  • 利用filter将偶数过滤出来

参考

  1. Swift中的函数式编程
  2. iOS面试之道

相关文章

网友评论

      本文标题:Swift函数式编程

      本文链接:https://www.haomeiwen.com/subject/nqgcbftx.html