美文网首页
swift常用高阶函数

swift常用高阶函数

作者: SPIREJ | 来源:发表于2019-08-19 14:29 被阅读0次

    swift常用的高阶函数mapflatMapfilterreduce

    1. map

    /// -参数转换:映射闭包。接受一个“变换”元素作为其参数,并返回转换后的值(相同或不同类型的值)。
    /// -返回:包含转换后的元素的数组序列。
    @inlinable public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
    

    来看一个例子,就能秒懂
    在本例中,首先使用map转换数组中的名称
    转换为小写字符串,然后计算它们的字符数。

    let cast = ["Vivien", "Marlon", "Kim", "Karl"]
    let lowercaseNames = cast.map { $0.lowercased() }
    
    // 'lowercaseNames' == ["vivien", "marlon", "kim", "karl"]
    let letterCounts = cast.map { $0.count }
    // 'letterCounts' == [6, 6, 3, 4]
    
    /// 第一次返回的是数组,也可以map连写
    let res = cast.map { (str) -> String in
        str.lowercased()
        }.map { (str) -> Int in
            str.count
    }
    // 'res' = [6, 6, 3, 4]
    
    let res1 = cast.map {
        $0.lowercased()
        }.map {
            $0.count
    }
    // 'res1' = [6, 6, 3, 4]
    

    2. flatMap

    /// -参数转换:接受此元素的闭包,返回一个序列或集合。
    /// -返回:生成的扁平数组。
    /// -复杂度:O(*m* + *n*),其中*n*是这个序列的长度和*m*是结果的长度。
    @inlinable public func flatMap<SegmentOfResult>(_ transform: (Element) throws -> SegmentOfResult) rethrows -> [SegmentOfResult.Element] where SegmentOfResult : Sequence
    
    1. map和flatMap的区别

    相同点:
    mapflatMap都可以用在OptionalsSequenceTypes上(如:数组、字典等)。

    不同点:
    map对这个序列的每个元素进行转换。
    flatMap会将转换(transform)函数的返回类型先拍扁,在组合成本身的复合类型

    看一个例子

    let numbers = [1, 2, 3, 4]
    let mapped = numbers.map { Array(repeating: $0, count: $0) }
    // [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
    
    let flatMapped = numbers.flatMap { Array(repeating: $0, count: $0) }
    // [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
    

    请注意上面使用mapflatMap,带有返回数组的转换的结果。实际上s.flatMap(transform)相当于Array(s.map(transform). joined())

    2. compactMap

    Swift4.1新加入的新特性compactMap;
    对序列的每个元素进行转换,返回非nil结果

    @available(swift, deprecated: 4.1, renamed: "compactMap(_:)", message: "Please use compactMap(_:) for the case where closure returns an optional value")
    
    public func flatMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
    
    /// -参数转换:接受此元素的闭包,序列作为它的参数,并返回一个可选值。
    /// -返回:调用“transform”的非“nil”结果的数组序列的每个元素。
    /// -复杂度:O(*m* + *n*),其中*n*是这个序列的长度和*m*是结果的长度。
    @inlinable public func compactMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]
    

    看一个例子
    map返回有可选值nil
    compactMap返回的是剔除可选值的结果

    let possibleNumbers = ["1", "2", "three", "///4///", "5"]
    
    let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
    //[Optional(1), Optional(2), nil, nil, Optional(5)]
    
    let compactMapped: [Int] = possibleNumbers.compactMap { str in Int(str) }
    // [1, 2, 5]
    
    3. 什么时候用 flatMap、compactMap

    当类型转换时有可能装换为可选类型的时候,用compactMap,不会装换为可选类型的咱们直接用flatMap

    比如我们有一个数组

    let array = ["Apple", "Orange", "Puple", "sss"]
    

    我们想要返回每个元素的长度的时候,转换时返回类型是Int?时,这个时候不能确保转换成功,就需要用compactMap

    let array = ["Apple", "Orange", "Puple", "sss"]
    
    let sss = array.flatMap { (str) -> String in
        str
    }
    
    let arr2 = array.compactMap { a -> Int? in
        return a.count
    }
    

    3. filter

    filter过滤器,可以取出数组中符合条件的元素,重新组成一个新的数组

    let numbers = [1,2,3,4,5,6]
    let evens = numbers.filter { $0 % 2 == 0 }
    // [2, 4, 6]
    

    4. reduce

    有的时候我们需要把所有元素的值合并成成一个新的值,就用到了reduce

    /// -参数:
    /// - initialResult:用作初始累积值的值。“initialResult”第一次被传递给“nextPartialResult”执行闭包。
    /// - nextPartialResult:一个包含累积值和的闭包, 将序列中的一个元素转换成一个新的累加值,待用在“nextPartialResult”闭包或返回到的下一个调用中
    /// -返回:最终的累积值。如果序列没有元素,结果是“initialResult”。
    /// -复杂度:O(*n*),其中*n*是序列的长度。
    @inlinable public func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
    

    来看下面这个例子

    let numbers = [1, 2, 3, 4]
    let numberSum = numbers.reduce(0, { x, y in
        x + y
    })
    // numberSum == 10
    

    当调用numbers.reduce(_:_:)时,执行以下步骤:
    1。使用initialResult——0调用nextPartialResult闭包,在这种情况下——调用numbers的第一个元素,返回sum:' 1 '
    2。使用前一个调用的返回重复调用闭包值和序列的每个元素。
    3。当序列用完时,从闭包返回给调用者。
    如果序列没有元素,则永远不会执行nextPartialResultinitialResult是调用reduce(_:_:)的结果。

    1. 合并成的新值不一定跟原数组中元素的类型相同

    let numbers = [1,3,5,6,9,4,0,0,9,8,8]
    let tel = numbers.reduce("") {
        "\($0)" + "\($1)"
    }
    //13569400988 String类型
    

    2. ruduce 还可以实现 mapfilter 并且时间复杂度变为O(n) 原来 mapfilter 的时间复杂度是O(n*n)

    extension Array {
        func mMap<U>(transform: (Element) -> U) -> [U] {
            return reduce([], {
                $0 + [transform($1)]
            })
        }
        
        func mFilter (includeElement: (Element) -> Bool) -> [Element] {
            return reduce([]) { includeElement($1) ? $0 + [$1] : $0 }
        }
    }
    

    写在最后

    我们看SequenceTypes上的方法和函数有这么多,学无止境,慢慢探索

    相关文章

      网友评论

          本文标题:swift常用高阶函数

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