Swift超基礎(chǔ)語(yǔ)法(元組篇)

你對(duì)Swift中的元組了解多少呢?
...
很有自信嘛
...
看完這篇文章再說(shuō)嘍

元組

  • 元組是Swift中特有的,OC中并沒(méi)有相關(guān)數(shù)據(jù)類型
  • 元組是一種數(shù)據(jù)結(jié)構(gòu),它可以把多個(gè)值,組成一個(gè)復(fù)合值,元組內(nèi)元素的類型無(wú)需相同

元組的定義格式:

let 元組名稱 = (元素,元素...)

數(shù)組?字典?元組!

  • 使用數(shù)組定義的數(shù)據(jù)
    缺點(diǎn):在一個(gè)數(shù)組中,如果存在多種數(shù)據(jù)類型,所有的元素類型都將會(huì)一并變?yōu)?strong>NSObject
例:
let infoArray = ["lyu" , 18]
let name = infoArray[0] //缺點(diǎn):name的類型是NSObject,而不是String,也就是說(shuō)我們是沒(méi)有辦法敲出name.characters這個(gè)方法的
let length = name.characters.count  //編譯報(bào)錯(cuò)
  • 使用字典定義的數(shù)據(jù)
    缺點(diǎn):在一個(gè)字典中,如果其value值存在多種數(shù)據(jù)類型,所有的value類型都將會(huì)一并變?yōu)?strong>NSObject
例:
let infoDic = ["name" : "lyu" , "age" : 18]
let name = infoDic["name"]  //缺點(diǎn):name的類型是NSObject,而不是String,也就是說(shuō)我們是沒(méi)有辦法敲出name.characters這個(gè)方法的
let length = name.characters.count  //編譯報(bào)錯(cuò)
  • 使用元組來(lái)定義數(shù)據(jù):
    優(yōu)點(diǎn):元組中的數(shù)據(jù)是按照他們的真實(shí)類型來(lái)存儲(chǔ)的
例:
let infoTuple = ("lyu" , 18)  //元組會(huì)為他的元素儲(chǔ)存其真實(shí)類型
let name = infoTuple.0  //name的類型為String
let length = name.characters.count  //毫無(wú)壓力的拿到字符串的長(zhǎng)度

元組的使用方法

  • 給元組中的元素起別名
例:
let errorTuple = (newName : "Not Found" , newCode : 404)
let errorName = errorTuple.newName
let errorCode = errorTuple.newCode
//當(dāng)然.0和.1仍然可以取值
let errorName1 = errorTuple.0
let errorCode1 = errorTuple.1
  • 給元組起別名的另一種方法:
    要注意的是,通過(guò)這種方法來(lái)創(chuàng)建元組是拿不到元組名字的
    缺點(diǎn):拿不到元組的名字
    優(yōu)點(diǎn):快速解構(gòu)
例:
let (newName , newCode) = ("Not Found" , 404)
let errorName = newName
let errorCode = newCode
提示:這種方法來(lái)創(chuàng)建的元組相當(dāng)于直接創(chuàng)建了兩個(gè)常量

元組的進(jìn)階使用方法

  • 與Switch搭配進(jìn)行復(fù)雜條件的判斷:
例:招聘一個(gè)20歲以下的員工,并同時(shí)打印其個(gè)人信息
        let name = "lyu"  //姓名
        let age = 18  //年齡
        var personalInfo = [String : NSObject]()  //個(gè)人信息
        personalInfo["height"] = 1.80  //個(gè)人信息
        switch (age,name,personalInfo) {  //包裝元組,元組中元素的命名要與姓名,年齡,個(gè)人信息完全一致
        case (let age , let name , let personalInfo) where age < 20:  //滿足age<20則執(zhí)行case
            print(age)
            print(name)
            print(personalInfo)
        default:
            print(age)
        }
  • 作為函數(shù)的返回值,來(lái)創(chuàng)建多個(gè)返回值的函數(shù)
例:計(jì)算一個(gè)數(shù)組中奇數(shù)偶數(shù)的值,一并返回
        func getCount(nums : [Int]) -> (Int , Int) {  //將返回值構(gòu)建為一個(gè)元組
            var oddCount = 0  //初始化偶數(shù)個(gè)數(shù)
            var evenCount = 0  //初始化奇數(shù)個(gè)數(shù)
            for num in nums {  //遍歷數(shù)組
                if num % 2 == 0 {  判斷是否為偶數(shù)   
                    oddCount += 1
                }
                else  //反之為奇數(shù)
                {
                    evenCount += 1
                }
            }
            return (oddCount , evenCount) 返回元組:(偶數(shù),奇數(shù))
        }
        let nums = [12,14,15,2,77,13]
        let counts = getCount(nums)
        print(counts)
        print(counts.0)
        print(counts.1)
  • 函數(shù)作為元組的元素,進(jìn)行多函數(shù)同時(shí)調(diào)用
例:
        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)
  • 交換值
    被交換的必須是變量,并且這兩個(gè)變量類型必須相同
例:
        var (x , y) = (11 , 22)
        (x , y) = (y , x)
        print(x , y)

元組的超進(jìn)階使用方法

  • 以假亂真:使用元組代替結(jié)構(gòu)體
例:
        //定義結(jié)構(gòu)體
        struct newS {
            var name : String
            var age : Int
        }
        let temp = newS(name : "lyu" , age :18)
        //定義元組
        let tuple = (name : "lyu" , age : 18)
        //使用元組和結(jié)構(gòu)體
        print(tuple.name)
        print(temp.name)
Tips:結(jié)構(gòu)體?元組?
我們發(fā)現(xiàn)這兩個(gè)家伙還是有所不同的:元組并沒(méi)有結(jié)構(gòu)體的聲明部分,所以如果只是臨時(shí)使用,或臨時(shí)拼湊一個(gè)結(jié)構(gòu)體,那么建議使用元組
如果你的需求超出了"臨時(shí)"(根據(jù)你的代碼自己判斷嘍~)的范圍,那么還是建議將數(shù)據(jù)封裝成結(jié)構(gòu)體
另外:也可以使用元組來(lái)代替"匿名結(jié)構(gòu)體哦"
  • 處理數(shù)據(jù)的過(guò)程中,將某一個(gè)函數(shù)的返回值作為臨數(shù)據(jù)傳入另一方法中
    • 元組可以作為函數(shù)的參數(shù)
    • 元組也可以作為函數(shù)的返回值,既然如此,這種用法當(dāng)然也可以成立了
//元組作為函數(shù)返回值
func getViewInfo() -> (r : Int , alpha : Double , location : (Double , Double)){
        return (255 , 0.5 , (100 , 100))
}
//元組作為函數(shù)參數(shù)
func getAlpha(tuple : (r : Int , alpha : Double , location : (Double , Double))) -> Double{  
        return tuple.alpha
}
let alpha = getAlpha(getViewInfo())
print(alpha)
  • 當(dāng)然根據(jù)上一條使用方法,我們也可以想到本例也可以使用結(jié)構(gòu)體來(lái)實(shí)現(xiàn),如下:
        //聲明結(jié)構(gòu)體
        struct Location {
            var x : Double
            var y : Double
        }
        struct Info {
            var r : Int
            var alpha : Double
            var location : Location
        }
        //定義函數(shù)
        func getViewInfo() -> (Info){
            return Info(r: 255 , alpha: 0.5 , location: Location(x: 100 , y: 100))
        }
        func getAlpha(stc : Info) -> Double{
            return stc.alpha
        }
        //調(diào)用函數(shù)
        let alpha = getAlpha(getViewInfo())
        print(alpha)
tips:
為了兩個(gè)函數(shù)而刻意定義兩個(gè)結(jié)構(gòu)體,這種做法顯然太浪費(fèi)了,所以這里才為大家介紹了上面元組代替結(jié)構(gòu)體的方法
  • 具體定義元組類型
        //typealias相當(dāng)于C/OC中的typedef,用于起別名
        typealias Tuple = (name : String , age : Int ,height : Double)  //這與結(jié)構(gòu)體的聲明及其相似
        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))
  • 約束一個(gè)類型元素的個(gè)數(shù)
    當(dāng)我們創(chuàng)建一個(gè)數(shù)組可變數(shù)組,并且希望這個(gè)數(shù)組未來(lái)存儲(chǔ)7組數(shù)據(jù),例如統(tǒng)計(jì)一周內(nèi)的每日降雨量
//做法1:我們首先想到使用一個(gè)數(shù)組來(lái)包裝這7天的數(shù)據(jù)
        var info = [Int]()
        info.append(11)
//缺點(diǎn):這種做法沒(méi)辦法控制數(shù)組中元素的數(shù)量,如果外界添加元素的時(shí)候不小心添加了8個(gè),就沒(méi)辦法按地球的邏輯解釋了,難道真的有星期八~
//做法2:使用元組包裝數(shù)據(jù)
var info : (Int,Int,Int,Int,Int,Int,Int,Int)  //什么?不是7個(gè),一定是你擼多眼花了
//優(yōu)點(diǎn):這樣做可以把info中的元素個(gè)數(shù)約束為7個(gè),多于少于7都會(huì)報(bào)錯(cuò)
  • 作為函數(shù)的可變參數(shù)
    當(dāng)函數(shù)的參數(shù)數(shù)量不確定的時(shí)候
例:
func sum(numbers : Int...) -> Int{
            return numbers.reduce(0, combine: +)  //第一個(gè)參數(shù)為基值,代表在0的基礎(chǔ)上累加
        }
        let result = sum(1,2,3)
  • 元組與泛型
    元組中元素的真實(shí)類型是根據(jù)元組中元素類型來(lái)確定的,所以與其讓泛型來(lái)約束元組,還不如根據(jù)我們的需求來(lái)定義一個(gè)明確數(shù)據(jù)類型的元組,反過(guò)來(lái)控制泛型
    • 由元組的類型來(lái)指定函數(shù)的泛型
        //例:元組與泛型與函數(shù)
        func three<c1 , c2 , c3>(tuple : (c1 , c2 , c3)) -> c3{  //利用泛型來(lái)聲明元組屬性類型,此時(shí)元組的屬性類型與泛型都還是不確定的
            return tuple.2
        }
        //隨便傳入一個(gè)元組,均可成功調(diào)用該函數(shù)
        let  height = three(("Lyu" , 18 , 1.88))  //調(diào)用three函數(shù)的那一時(shí)刻,Swift根據(jù)參數(shù)(元組)類型推導(dǎo)出three的泛型!此時(shí)拿到的height是明確的Double類型
  • 根據(jù)需求,由子類來(lái)指定父類泛型
        例:元組與泛型與類
        class superClass<c1 , c2 , c3>{  //定義父類,此時(shí)泛型不確定
            typealias numbers = (c1 , c2 , c3)  //利用此時(shí)不確定的泛型來(lái)聲明一個(gè)元組
            func printNewNumbers(nums : numbers) -> Void {
                print(nums)
            }
        }
        class childClass<c1 , c2 , c3> : superClass<c1 , c2 , c3> {  //定義子類,此時(shí)父類的泛型與子類相同,但子類的泛型不確定
        }
        let child = childClass<String , Int , Double>()  //實(shí)例化對(duì)象,我們可以在此處根據(jù)需求來(lái)確定泛型,此時(shí)父類與子類泛型均以確定,
        child.printNewNumbers(("lyu" , 18 , 1.80))  //創(chuàng)建元組作為參數(shù)
        //當(dāng)然我們也可以這樣寫
        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> {  //在此處確定元組中某一個(gè)元素的類型(當(dāng)然,前提你真的確定這個(gè)元素的類型...)
        }
        let child = childClass<String , Int>()  //這時(shí),我們只需要確定前兩個(gè)元素的類型即可
        child.printNewNumbers(("lyu" , 18 , 1.80))
tips:
當(dāng)我們需要封裝一個(gè)函數(shù),但卻不明確要傳入的參數(shù)(不只是元組),可以利用這種思想,舉一個(gè)最簡(jiǎn)單的例子如下:
        func myNameOrAge<c1>(nameOrAge : c1) -> c1{
            return nameOrAge
        }
        let name = myNameOrAge("Lyu")  //這里name的類型是String而不是可選類型,也不是anyObject
        let age = myNameOrAge(18)  //這里age的類型是Int而不是可選類型,也不是anyObject
也就是說(shuō):此時(shí)反過(guò)來(lái)看return nameOrAge這一句中已經(jīng)拿到了nameOrAge的真是類型,假如我們?cè)诤瘮?shù)體內(nèi)做一些復(fù)雜的運(yùn)算,最終返回的值仍然是一個(gè)已知的類型,是不是比anyObject要好的多呢
  • 元組作為函數(shù)的參數(shù)
    • 利用有參元組,作為帶外部參數(shù)函數(shù)的參數(shù)
        func sum(a a : Int , b : Int , hello : String) -> Int {
            return a + b
        }
        let tuple = (a : 1,b : 2, hello : "hello")  //利用有參元組作為帶外部參數(shù)的函數(shù)的參數(shù)
        let result = sum(tuple)
  • 利用無(wú)參元組,作為不帶外部參數(shù)函數(shù)的參數(shù)
        func sum(a : Int , _ b : Int , _ hello : String) -> Int {
            return a + b
        }
        let tuple = (1 , 2 , "hello")  //利用無(wú)參元組作為不帶外部參數(shù)函數(shù)的參數(shù)
        let result = sum(tuple)
  • 一個(gè)函數(shù)返回的元組作為另一個(gè)函數(shù)的參數(shù)
        func getTuple() -> (Int , Int , String){
            return(1, 2, "hello")
        }
        func printTuple(tuple : (Int , Int , String)){
            print(tuple)
        }
        printTuple(getTuple())
        //這種傳遞方式可以讓我們無(wú)需結(jié)構(gòu)元組(返回值),即可完成多個(gè)數(shù)據(jù)的傳遞
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容