Swift 数组常用高阶函数

map
map会遍历数组的每个元素,遍历到一个元素,会调用一次闭包生成一个新的值,最终所有的值组成一个新的数组返回

var arr = [1, 2, 3, 4, 5]
var arr1 = arr.map { (i) -> Int in
    return i * 2
}
print(arr1) //[2, 4, 6, 8, 10]

//闭包表达式的简写
var arr1 = arr.map { $0 * 2 }
var arr = arr.map { "rulala_\($0)" }
print(arr) // ["rulala_1", "rulala_2", "rulala_3", "rulala_4", "rulala_5"]

模拟系统内部的实现方式,大概是这样的


extension Array {
    func test_map(_ block: ((Element) -> Element)) -> [Element] {

        var resultArray = [Element]()
        for item in self {
            let result = block(item)
            resultArray.append(result)
        }
        return resultArray
    }
}

filter
filter会遍历数组的每个元素,如果元素满足一定的条件,就进行筛选过滤,最终筛选结果生成一个新的数组返回

var arr = [1, 2, 3, 4, 5]
var arr2 = arr.filter { (i) -> Bool in
    return i % 2 == 0 // 返回所有偶数
}
print(arr2) //[2, 4]

//闭包表达式的简写
var arr2 = arr.filter { $0 % 2 == 0  }

模拟系统内部的实现方式,大概是这样的

extension Array {
    func test_filter(_ block: ((Element) -> Bool)) -> [Element] {

        var resultArray = [Element]()
        for item in self {
            let result = block(item)
            if result {
                resultArray.append(item)
            }
        }
        return resultArray
    }
}


reduce
reduce 会遍历数组的每个元素,每遍历到一次,就调用一次闭包

@inlinable public func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Self.Element) throws -> Result) rethrows -> Result

reduce的返回值类型是Result,跟参数initialResult一致,说明第一个参数传什么,返回值类型就是什么。nextPartialResult:接受两个参数,返回一个Result类型,nextPartialResult里面第一个参数的初始值就是initialResult的值,第二个参数是数组遍历到的每个元素。
例子里的result + element,就相当于数组每遍历一次,就将上一次的result跟元素element相加,赋值给下一次的result,直到遍历结束:

var arr = [1, 2, 3, 4, 5]
var arr3 = arr.reduce(0) { (result, element) -> Int in
    return result + element
}
print(arr3) //15

//简写
var arr3 = arr.reduce(0) { $0 + $1 }

如果换成result * element,结果就为0

var arr3 = arr.reduce(1) { (result, element) -> Int in
    return result * element
}
print(arr3) //120

  模拟系统内部的实现方式,大概是这样的

extension Array {
    func test_reduse<Result>(_ initResult : Result , _ block: ((Result, Element) -> Result)) -> Result {
        var result = initResult
        for item in self {
            result = block(result,item)
        }
        return result
    }

}


flatMap
先看个例子🌰

var arr = [1, 2, 3]

var arr1 = arr.map{ Array.init(repeating: $0, count: $0) }
print(arr1) // [[1], [2, 2], [3, 3, 3]]

var arr2 = arr.flatMap { Array.init(repeating: $0, count: $0) }
print(arr2) // [1, 2, 2, 3, 3, 3]

mapflatmap一样,最终都是生成一个新的数组返回,但是flatmap的区别是它会将内部的元素都拆开统一生成一个大的数组返回。(flat有平铺的意思,可以这么理解)

flatmap还能把多维数组变成一维数组:

var arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
 
var arr1 = arr.map{ $0 }
arr1 // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
 
var arr2 = arr.flatMap{ $0 }
arr2 // [1, 2, 3, 4, 5, 6, 7, 8, 9]

这个略微复杂一点,系统对flatMap的实现有2种,通过对函数入参的重载完成调用合适的函数,

第一个函数的入参是: (Element) -> [ElementOfResult], block返回数组

第二个函数的入参是:(Element) -> ElementOfResult,block返回单个元素

通过方法重载,系统会调用合适的函数,完成对二维数组的展开。

extension Array {
    func test_flatMap<ElementOfResult>(_ transform: (Element) -> [ElementOfResult]) -> [ElementOfResult] {
        var result = [ElementOfResult]()
        for element in self {
            let transformed = transform(element)
            result.append(contentsOf: transformed)
        }
        return result
    }

    func test_flatMap<ElementOfResult>(_ transform: (Element) -> ElementOfResult) -> [ElementOfResult] {
        var result = [ElementOfResult]()
        for element in self {
            let transformed = transform(element)
            result.append(transformed)
        }
        return result
    }
}


compactMap
当闭包中的返回结果是可选的时候,使用compactMap代替flatMap,同时在真正返回结果的时候,会自动过滤掉nil

var arr = [1, nil, 3, nil, 4, .none, Optional(6)]
var arr1 = arr.compactMap { $0 }
print(arr1) // [1, 3, 4, 6]

下面的字符串数组中,分别采用mapcompactMap遍历数组。在map强转失败就是nil,同时强转成功会处理成可选类型;而在compactMap中进行Int强转,不满足强转的元素会被当做nil过滤掉

var  arr = ["123", "test", "jack", "-39"]

var arr1 = arr.map { Int($0) }
print(arr2) // [Optional(123), nil, nil, Optional(-39)]

var arr2 = arr.compactMap { Int($0) }
print(arr2) // [123, -39]

这个还是比较简单的,和map实现类似,只是发现转换失败,进行过滤。

  模拟系统内部的实现方式,大概是这样的

extension Array {
    func test_compactMap<ElementResult>(_ block: (Element) -> ElementResult?) -> [ElementResult] {

        var resultArray = [ElementResult]()
        for item in self {
            if let result = block(item) {
                resultArray.append(result)
            }
        }
        return resultArray
    }
}

链接:https://www.jianshu.com/p/46205ad9317d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值