swift函数

定义与调用

1.普通样式

-> 来指定函数返回值类型

func greet(person: String, day: String) -> String{
    return "hello \(person), today is \(day)"
}
greet(person: "Bob", day: "Tuesday")
//"hello Bob, today is Tuesday"

2.忽略参数

_ 表示方法该参数,使用时不需要引入参数标签

func greet2(_ person: String, on day: String) -> String{
    return "hello \(person), today is \(day)"
}
greet2("Tino", on: "Wednesday")
//"hello Tino, today is Wednesday"

// 所有参数都不引入标签
func greet3(_ person: String, _ day: String) -> String{
    return "hello \(person), today is \(day)"
}
greet3("Xiaoming", "Wednesday")
//"hello Xiaoming, today is Wednesday"

3.默认参数值

func greet4(_ person: String = "Xiaoming", _ day: String = "Wednesday") -> String{
    return "hello \(person), today is \(day)"
}
greet4()
//"hello Xiaoming, today is Wednesday"

4.可变参数函数

一个函数最多只能拥有一个可变参数。

func greet5(_ persons: String...) -> String{
    var sayHello = ""
    for person in persons {
        sayHello = sayHello + "hello \(person) \n"
    }
    return sayHello
}
print(greet5("laoda","laoer","laosan","laosi","laowu","laoliu"))
/**
 hello laoda
 hello laoer
 hello laosan
 hello laosi
 hello laowu
 hello laoliu
 */

5.输入输出参数(inout修饰)

不能有默认值,而且可变参数不能用 inout 标记。

func swapTwoInts(_ a: inout Int , _ b: inout Int){
    let tmp = a
    a = b
    b = tmp
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is \(someInt), anotherInt is \(anotherInt)")
//someInt is 107, anotherInt is 3

函数类型

结合元组

// 1. 返回值为元组
func calculate(_ scores:[Int]) -> (max:Int , min:Int , total:Int , pass: Int){
    guard scores.count > 0 else {
        return (0,0,0,0)
    }
    var min = scores[0]
    var max = scores[0]
    var total = 0
    var pass = 0

    for score in scores {
        if score > max {
            max = score
        }
        if score < min {
            min = score
        }
        total += score
        if score > 60 {
            pass += 1
        }
    }
    return (max,min,total,pass)
}
print(calculate([10,20,70,80,55,39,100,65]))
//(max: 100, min: 10, total: 439, pass: 4)

// 2. 返回值为可选元组
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty { return nil }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

// 元组只能针对少量元素,超过6个以后各种运算会报错
var user1 = (name:"Bill", sex: true, age: 18, top: 180, weight:180 , hairColor: "yello", score: 80)
var user2 = (name:"Bill", sex: true, age: 18, top: 180, weight:180 , hairColor: "yello", score: 80)
//user1 == user2
//Binary operator '==' cannot be applied to two '(name: String, sex: Bool, age: Int, top: Int, weight: Int, hairColor: String, score: Int)' operands

// 3. 参数为元组
func transformModelToDict(_ x:(name: String, sex: Bool, age: Int)) -> [String: Any]{
    var dict:[String:Any] = [:]
    dict["name"] = x.name
    dict["sex"] = x.sex
    dict["age"] = x.age
    return dict
}
print(transformModelToDict((name: "yes", sex: true, age: 18)))
//["age": 18, "name": "yes", "sex": true]

let mirror = Mirror(reflecting: user1)
for (subLabel, value) in mirror.children {
    let label = String(describing: subLabel)
    switch value {
    case is Int:
        print("type is Int, label is \(label), value is \(value)")
    case is Bool:
        print("type is Bool, label is \(label), value is \(value)")
    case is String:
        print("type is String, label is \(label), value is \(value)")
    default:
        print("type isDefault, label is \(label), value is \(value)")
    }
}

// 4. 隐式返回的函数 省略return
func greeting(for person: String) -> String {
    "Hello, " + person + "!"
}
print(greeting(for: "Dave"))
// 打印 "Hello, Dave!"

函数嵌套

  1. 常规用法
func returnFifteen() -> Int{
    func returnFive() -> Int{
        return 5
    }
    func returnTen() -> Int{
        return returnFive() + returnFive()
    }
    return returnFive() + returnTen()
}
print(returnFifteen()) //15
// 或者这样用
func chooseFuncToUse(isadd: Bool) -> (Int) -> Int{
    func func1(input:Int) -> Int {input + 1}
    func func2(input:Int) -> Int {input - 1}
    return isadd ? func1 : func2
}
var tmp = 3
let theFunc = chooseFuncToUse(isadd: tmp < 0)
while tmp > 0{
    print("tmp is \(tmp)")
    tmp = theFunc(tmp)
}
/**
tmp is 3
tmp is 2
tmp is 1
*/
  1. 函数作为变量
var myfunc :() -> Int = returnFifteen // myfunc == returnFifteen
func oneFunc(_ a: Int, _ b: Int) -> Int{
    return a + b
}
var myfunc2 :(Int,Int) -> Int = oneFunc(_:_:) // myfunc2 == oneFunc
  1. 函数作为返回值,返回的是函数 (Int)->Int
func makeAdd() ->(Int) -> Int{
    func addOne(_ number: Int) -> Int{
        return number + 1
    }
    // 完整调用的写法  addOne(_:) ,下边是简写
    return addOne
}
let theAddOneFunc = makeAdd()//返回的是addOne(_:)函数
print(theAddOneFunc(2))//3
  1. 函数作为参数
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool{
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
let numbers = [20,19,7,12]
func lessThanTen(_ number: Int) -> Bool{
    if number < 10 {
        return true
    }
    return false
}
print(hasAnyMatches(list: numbers, condition: lessThanTen))//true
print(numbers.sorted())//[7, 12, 19, 20]
print(numbers.sorted{$0 > $1}) // [20, 19, 12, 7]

闭包

{}直接包起一个函数,in分割,前部为参数返回值,后部为函数实现

  • $ 操作符是代指遍历每一项元素
  • $0 就是函数传入的第一个参数,$1 就是第二个,以此类推...
// 简写
/// 闭包实际上是对函数的简化,下边的函数都是相同的结果,数组每项元素x10
let arrayOfInt = [2,3,4,5,4,7,2]
arrayOfInt.map({(someInt: Int) -> Int in return someInt * 10 })
arrayOfInt.map({(someInt: Int) in return someInt * 10 })
arrayOfInt.map({someInt in return someInt * 10 })
arrayOfInt.map({someInt in someInt * 10 })
arrayOfInt.map({$0 * 10 })
arrayOfInt.map{$0 * 10 }
// 整体*3
var newNumbers = numbers.map({
    (number: Int) -> Int in
    let result = 3 * number
    return result
})
// 判断奇偶
var checkResult = {(number : Int) -> (Int) in
    let result = number % 2
    if result == 1 {
        return 0
    }
    return number
}

print("numbers is \(numbers)")//"numbers is [20, 19, 7, 12]"
print("newNumbers is \(newNumbers)")//"newNumbers is [60, 57, 21, 36]"

高阶函数

1. map函数

func map(transform: (T) -> U) -> [U]

接受一个闭包作为规则,自动遍历集合的每一个元素,使用闭包的规则去处理这些元素,生成一个结构相同的集合

map使用

let cast = ["Vivien", "Marlon", "Kim", "Karl"]
let lowerCast = cast.map({$0.lowercased()})
print(lowerCast)//"["vivien", "marlon", "kim", "karl"]"
let castCount = cast.map({$0.count})
print(castCount)//"[6, 6, 3, 4]"
print(cast.map{"名字是 :\($0)"})//["名字是 :Vivien", "名字是 :Marlon", "名字是 :Kim", "名字是 :Karl"]
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)//[60, 57, 21, 36]
flatMap

接受一个闭包作为规则,自动遍历集合的每一个元素,使用闭包的规则去处理这些元素,将处理结果直接放入到一个新的集合里面,可以出现数组降维,并且会自动过滤nil(自动解包),如果是不包含nil元素的一维数组的和map的作用效果是一样的,所以推荐使用flatMap

map对象为数组时,将numbers数组的每个元素强制转换为{}内规则的类型,并按每一项拆分,生成一个新的一维数组

let numbers = [20,19,7,12]

/// 1.传入字符串: 强转String数组,将每一项与"的"字符拼接,按字符逐项拆分
let flatMapResult = numbers.flatMap({"\($0)的"})
//["2", "0", "的", "1", "9", "的", "7", "的", "1", "2", "的"]

/// 2.传入字符串数组:强转String数组,将参数数组每一项与原数组(现字符串数组)拼接,生成新的一维数组
let flatMapResult2 = numbers.flatMap({["\($0)的","他叫\($0)"]})
//["20的", "他叫20", "19的", "他叫19", "7的", "他叫7", "12的", "他叫12"]

/// 3.传入数字运算操作:numbers.flatMap({$0+1})系统警告,需用compactMap替换
// 数字运算操作时,需用compactMap替换flatMap
let compactMapResult = numbers.compactMap({$0+1})
//[21, 20, 8, 13]

/// compactMap会过滤掉不符合闭包规则的值,看下边的官方demo
let possibleNumbers = ["1", "2", "three", "///4///", "5"]

// map声明变量时Int类型必须带?
let mapped: [Int?] = possibleNumbers.map { str in Int(str) }
// [Optional(1), Optional(2), nil, nil, Optional(5)]

// compactMap声明变量时Int类型可以带,也可以不带
let compactMapped: [Int] = possibleNumbers.compactMap { str in Int(str) }
// Int类型时,会过滤nil,结果[1, 2, 5]
// Int?类型时,不会过滤nil,结果[Optional(1), Optional(2), nil, nil, Optional(5)]

/// 4.传入字典操作:将原数组每一个元素都变为一个字典
let flatMapResult3 = numbers.flatMap({["\($0)":"他叫\($0)"]})
//[(key: "20", value: "他叫20"), (key: "19", value: "他叫19"), (key: "7", value: "他叫7"), (key: "12", value: "他叫12")]

/// 5.数组降维操作,一次flatMap操作只能降低一层维度
let numbers2 = [[[1,2,3],[4,5,6],[7,8,9]],[10,11,12]]
let flatMapResult4 = numbers2.flatMap({$0})
//[[1, 2, 3], [4, 5, 6], [7, 8, 9], 10, 11, 12]

map对象为字典时

let dict = ["1":"4","2":"5","3":"6"]
let flatMapDictResult:[Int] = dict.compactMap({Int($1)})
// [6, 5, 4]
let flatMapDictResult2 = dict.map{(key,value) in key.capitalized}
//["1", "2", "3"]
应用:

举例,从一个model数组内,获取一个uid是否存在

let model1 = (uid:111,index:1)
let model2 = (uid:222,index:2)
let model3 = (uid:333,index:3)
let models = [model1,model2,model3]
// 原先方法
func checkUidExist(_ uid: Int) -> Bool{
    for model in models {
        if model.uid == uid {
           return true
        }
    }
    return false
}
// map方法
func checkUidExist2(_ uid: Int) -> Bool{
    let uids = models.map({$0.uid})
    return uids.contains(uid)
}
print(checkUidExist(000))//false

print(checkUidExist2(000))//false
2. filter函数

func filter(includeElement: (T) -> Bool) -> [T]

接受一个闭包作为筛选规则,自动遍历集合的每一个元素,保留符合闭包规则的元素,生成一个新的集合

对比

/// 下边是一个取奇数数组的例子
func newListOfOddLevel(_ array: [Int]) -> [Int] {
    var newList = [Int]()
    for item in array {
        if item % 2 == 1 {
            newList.append(item)
        }
    }
    return newList
}
let arrayOfIntegers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
/// 常规操作
print(newListOfOddLevel(arrayOfIntegers)) // [1, 3, 5, 7, 9]

// filter函数
let filterResult1 = arrayOfIntegers.filter {$0%2 == 1}
print(filterResult1) // [1, 3, 5, 7, 9]
3. reduce函数

func reduce(initial: U, combine: (U, T) -> U) -> U

接受一个初始化值,并且接受一个闭包作为规则,自动遍历集合的每一个元素,使用闭包的规则去处理这些元素,合并处理结果,返回结果是一个值
Returns the result of combining the elements of the sequence using the given closure(重点在于combining

可以简单理解成累加器,累积操作

// 数字串
let arrayOfFloat = [2.0, 3.0, 4.0, 5.0, 7.0]
let total = arrayOfFloat.reduce(0, +) // 21
// 字符串
let arrayOfString = ["abc","def","ghi"]
let totalString = arrayOfString.reduce("", +) // abcdefghi

// 输出新串
let customStr = arrayOfString.reduce("111") { (Result, arrayOfString) in
    "\(Result) , \(arrayOfString)"
}
print(customStr) // 111 , abc , def , ghi

let packages = [
    (name: "Swift高阶函数编程", number: 1, price: 80.0, address: "来广营"),
    (name: "Swift面向协议编程", number: 2, price: 88.0, address: "西二旗"),
    (name: "Swift基础", number: 3, price: 35.0, address: "798"),
    (name: "Swift进阶", number: 4, price: 50.0, address: "中关村")
]

let reduceName = packages.reduce("/") {$0 + $1.name}
print(reduceName) 
// Swift高阶函数编程Swift面向协议编程Swift基础Swift进阶

对比

func sum(_ initialResult : Int, _ array : [Int]) -> Int {
    var result = initialResult
    for item in array {
        result += item
    }
    return result
}
print(sum(10, arrayOfInt))// 37
print(arrayOfInt.reduce(10, +)) // 37
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345