Swift超基础语法(元组篇)

作者: S_Lyu | 来源:发表于2016-07-30 02:01 被阅读401次

你对Swift中的元组了解多少呢?
...
很有自信嘛
...
看完这篇文章再说喽

元组

  • 元组是Swift中特有的,OC中并没有相关数据类型
  • 元组是一种数据结构,它可以把多个值,组成一个复合值,元组内元素的类型无需相同

元组的定义格式:

let 元组名称 = (元素,元素...)

数组?字典?元组!

  • 使用数组定义的数据
    缺点:在一个数组中,如果存在多种数据类型,所有的元素类型都将会一并变为NSObject
例:
let infoArray = ["lyu" , 18]
let name = infoArray[0] //缺点:name的类型是NSObject,而不是String,也就是说我们是没有办法敲出name.characters这个方法的
let length = name.characters.count  //编译报错
  • 使用字典定义的数据
    缺点:在一个字典中,如果其value值存在多种数据类型,所有的value类型都将会一并变为NSObject
例:
let infoDic = ["name" : "lyu" , "age" : 18]
let name = infoDic["name"]  //缺点:name的类型是NSObject,而不是String,也就是说我们是没有办法敲出name.characters这个方法的
let length = name.characters.count  //编译报错
  • 使用元组来定义数据:
    优点:元组中的数据是按照他们的真实类型来存储的
例:
let infoTuple = ("lyu" , 18)  //元组会为他的元素储存其真实类型
let name = infoTuple.0  //name的类型为String
let length = name.characters.count  //毫无压力的拿到字符串的长度

元组的使用方法

  • 给元组中的元素起别名
例:
let errorTuple = (newName : "Not Found" , newCode : 404)
let errorName = errorTuple.newName
let errorCode = errorTuple.newCode
//当然.0和.1仍然可以取值
let errorName1 = errorTuple.0
let errorCode1 = errorTuple.1
  • 给元组起别名的另一种方法:
    要注意的是,通过这种方法来创建元组是拿不到元组名字的
    缺点:拿不到元组的名字
    优点:快速解构
例:
let (newName , newCode) = ("Not Found" , 404)
let errorName = newName
let errorCode = newCode
提示:这种方法来创建的元组相当于直接创建了两个常量

元组的进阶使用方法

  • 与Switch搭配进行复杂条件的判断:
例:招聘一个20岁以下的员工,并同时打印其个人信息
        let name = "lyu"  //姓名
        let age = 18  //年龄
        var personalInfo = [String : NSObject]()  //个人信息
        personalInfo["height"] = 1.80  //个人信息
        switch (age,name,personalInfo) {  //包装元组,元组中元素的命名要与姓名,年龄,个人信息完全一致
        case (let age , let name , let personalInfo) where age < 20:  //满足age<20则执行case
            print(age)
            print(name)
            print(personalInfo)
        default:
            print(age)
        }
  • 作为函数的返回值,来创建多个返回值的函数
例:计算一个数组中奇数偶数的值,一并返回
        func getCount(nums : [Int]) -> (Int , Int) {  //将返回值构建为一个元组
            var oddCount = 0  //初始化偶数个数
            var evenCount = 0  //初始化奇数个数
            for num in nums {  //遍历数组
                if num % 2 == 0 {  判断是否为偶数   
                    oddCount += 1
                }
                else  //反之为奇数
                {
                    evenCount += 1
                }
            }
            return (oddCount , evenCount) 返回元组:(偶数,奇数)
        }
        let nums = [12,14,15,2,77,13]
        let counts = getCount(nums)
        print(counts)
        print(counts.0)
        print(counts.1)
  • 函数作为元组的元素,进行多函数同时调用
例:
        func test1() -> String{
            return "test1"
        }
        func test2() -> String{
            return "test2"
        }
        func test3() -> String{
            return "test3"
        }
        let funcTuple = (a : test1() , b : test2() , c : test3())
        print(funcTuple)
  • 交换值
    被交换的必须是变量,并且这两个变量类型必须相同
例:
        var (x , y) = (11 , 22)
        (x , y) = (y , x)
        print(x , y)

元组的超进阶使用方法

  • 以假乱真:使用元组代替结构体
例:
        //定义结构体
        struct newS {
            var name : String
            var age : Int
        }
        let temp = newS(name : "lyu" , age :18)
        //定义元组
        let tuple = (name : "lyu" , age : 18)
        //使用元组和结构体
        print(tuple.name)
        print(temp.name)
Tips:结构体?元组?
我们发现这两个家伙还是有所不同的:元组并没有结构体的声明部分,所以如果只是临时使用,或临时拼凑一个结构体,那么建议使用元组
如果你的需求超出了"临时"(根据你的代码自己判断喽~)的范围,那么还是建议将数据封装成结构体
另外:也可以使用元组来代替"匿名结构体哦"
  • 处理数据的过程中,将某一个函数的返回值作为临数据传入另一方法中
    • 元组可以作为函数的参数
    • 元组也可以作为函数的返回值,既然如此,这种用法当然也可以成立了
//元组作为函数返回值
func getViewInfo() -> (r : Int , alpha : Double , location : (Double , Double)){
        return (255 , 0.5 , (100 , 100))
}
//元组作为函数参数
func getAlpha(tuple : (r : Int , alpha : Double , location : (Double , Double))) -> Double{  
        return tuple.alpha
}
let alpha = getAlpha(getViewInfo())
print(alpha)
  • 当然根据上一条使用方法,我们也可以想到本例也可以使用结构体来实现,如下:
        //声明结构体
        struct Location {
            var x : Double
            var y : Double
        }
        struct Info {
            var r : Int
            var alpha : Double
            var location : Location
        }
        //定义函数
        func getViewInfo() -> (Info){
            return Info(r: 255 , alpha: 0.5 , location: Location(x: 100 , y: 100))
        }
        func getAlpha(stc : Info) -> Double{
            return stc.alpha
        }
        //调用函数
        let alpha = getAlpha(getViewInfo())
        print(alpha)
tips:
为了两个函数而刻意定义两个结构体,这种做法显然太浪费了,所以这里才为大家介绍了上面元组代替结构体的方法
  • 具体定义元组类型
        //typealias相当于C/OC中的typedef,用于起别名
        typealias Tuple = (name : String , age : Int ,height : Double)  //这与结构体的声明及其相似
        func printTuple(tempTuple : Tuple){  //使用Tuple类型定义形参
            print(tempTuple)
        }
        //下面提供三种用法
        printTuple((name: "lyu" , age : 18 , height : 1.80))
        printTuple(Tuple("lyu" , 18 , 1.80))
        printTuple(("lyu" , 18 , 1.80))
  • 约束一个类型元素的个数
    当我们创建一个数组可变数组,并且希望这个数组未来存储7组数据,例如统计一周内的每日降雨量
//做法1:我们首先想到使用一个数组来包装这7天的数据
        var info = [Int]()
        info.append(11)
//缺点:这种做法没办法控制数组中元素的数量,如果外界添加元素的时候不小心添加了8个,就没办法按地球的逻辑解释了,难道真的有星期八~
//做法2:使用元组包装数据
var info : (Int,Int,Int,Int,Int,Int,Int,Int)  //什么?不是7个,一定是你撸多眼花了
//优点:这样做可以把info中的元素个数约束为7个,多于少于7都会报错
  • 作为函数的可变参数
    当函数的参数数量不确定的时候
例:
func sum(numbers : Int...) -> Int{
            return numbers.reduce(0, combine: +)  //第一个参数为基值,代表在0的基础上累加
        }
        let result = sum(1,2,3)
  • 元组与泛型
    元组中元素的真实类型是根据元组中元素类型来确定的,所以与其让泛型来约束元组,还不如根据我们的需求来定义一个明确数据类型的元组,反过来控制泛型
    • 由元组的类型来指定函数的泛型
        //例:元组与泛型与函数
        func three<c1 , c2 , c3>(tuple : (c1 , c2 , c3)) -> c3{  //利用泛型来声明元组属性类型,此时元组的属性类型与泛型都还是不确定的
            return tuple.2
        }
        //随便传入一个元组,均可成功调用该函数
        let  height = three(("Lyu" , 18 , 1.88))  //调用three函数的那一时刻,Swift根据参数(元组)类型推导出three的泛型!此时拿到的height是明确的Double类型
  • 根据需求,由子类来指定父类泛型
        例:元组与泛型与类
        class superClass<c1 , c2 , c3>{  //定义父类,此时泛型不确定
            typealias numbers = (c1 , c2 , c3)  //利用此时不确定的泛型来声明一个元组
            func printNewNumbers(nums : numbers) -> Void {
                print(nums)
            }
        }
        class childClass<c1 , c2 , c3> : superClass<c1 , c2 , c3> {  //定义子类,此时父类的泛型与子类相同,但子类的泛型不确定
        }
        let child = childClass<String , Int , Double>()  //实例化对象,我们可以在此处根据需求来确定泛型,此时父类与子类泛型均以确定,
        child.printNewNumbers(("lyu" , 18 , 1.80))  //创建元组作为参数
        //当然我们也可以这样写
        class superClass<c1 , c2 , c3>{
            typealias numbers = (c1 , c2 , c3)
            func printNewNumbers(nums : numbers) -> Void {
                print(nums)
            }
        }
        class childClass<c1 , c2> : superClass<c1 , c2 , Double> {  //在此处确定元组中某一个元素的类型(当然,前提你真的确定这个元素的类型...)
        }
        let child = childClass<String , Int>()  //这时,我们只需要确定前两个元素的类型即可
        child.printNewNumbers(("lyu" , 18 , 1.80))
tips:
当我们需要封装一个函数,但却不明确要传入的参数(不只是元组),可以利用这种思想,举一个最简单的例子如下:
        func myNameOrAge<c1>(nameOrAge : c1) -> c1{
            return nameOrAge
        }
        let name = myNameOrAge("Lyu")  //这里name的类型是String而不是可选类型,也不是anyObject
        let age = myNameOrAge(18)  //这里age的类型是Int而不是可选类型,也不是anyObject
也就是说:此时反过来看return nameOrAge这一句中已经拿到了nameOrAge的真是类型,假如我们在函数体内做一些复杂的运算,最终返回的值仍然是一个已知的类型,是不是比anyObject要好的多呢
  • 元组作为函数的参数
    • 利用有参元组,作为带外部参数函数的参数
        func sum(a a : Int , b : Int , hello : String) -> Int {
            return a + b
        }
        let tuple = (a : 1,b : 2, hello : "hello")  //利用有参元组作为带外部参数的函数的参数
        let result = sum(tuple)
  • 利用无参元组,作为不带外部参数函数的参数
        func sum(a : Int , _ b : Int , _ hello : String) -> Int {
            return a + b
        }
        let tuple = (1 , 2 , "hello")  //利用无参元组作为不带外部参数函数的参数
        let result = sum(tuple)
  • 一个函数返回的元组作为另一个函数的参数
        func getTuple() -> (Int , Int , String){
            return(1, 2, "hello")
        }
        func printTuple(tuple : (Int , Int , String)){
            print(tuple)
        }
        printTuple(getTuple())
        //这种传递方式可以让我们无需结构元组(返回值),即可完成多个数据的传递

相关文章

  • Swift超基础语法(元组篇)

    你对Swift中的元组了解多少呢?...很有自信嘛...看完这篇文章再说喽 元组 元组是Swift中特有的,OC中...

  • swift基础语法(元组)

    一、元组的介绍1、元组是Swift中特有的,OC中并没有相关类型2、它是什么呢?它是一种数据结构,在数学中应用广泛...

  • Swift超基础语法(基础篇)

    常量 定义常量的方法 我们先看一下最完整的定义常量的书写格式: Swift中的类型推导(不是推倒,别激动):如果在...

  • Swift超基础语法(函数篇)

    函数 定义函数的格式 Swift中的函数与OC中的方法比较相似,其格式如下: Swift中的函数相比于OC方法更为...

  • Swift超基础语法(is与as篇)

    类型判断(is) 还记OC中有下面这么一个方法么? 然而Swift中并没有这个方法,取而代之的是is这个关键字,它...

  • Swift基础语法简介(二)——元组

    元组把多个值合并成单一的复合型的值。元组内的值可以是任何类型,而且可以不必是同一类型。 元组是关系数据库中的基...

  • Swift超基础语法(可选链篇)

    可选链 官方的说法是:由多个可选类型组成的一个链条被称为可选链 然而他的可选性实际上体现在:我们当前调用的目标可能...

  • Swift超基础语法(闭包篇)

    "闭包,Swift中的新概念,然而除了写法不同,实际上用法与用途都和OC中的Block没什么不同" 闭包 Swif...

  • swift 基础语法

    swift 基础语法

  • Swift超基础语法(OC与Swift互用篇)

    OC与Swift的相互调用 总有一些迫不得已的情况,让我们不得不在Swift中使用OC代码,或是在OC中使用Swi...

网友评论

    本文标题:Swift超基础语法(元组篇)

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