美文网首页
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