有了陣列和字典,為何Swift還需要元組(tuples)?
**### 為什麼需要元組
為了回答這個問題,首先讓我們腦補一個例子:\
假設有一個班級,數學科目經常小測((⊙o⊙)),數學老師非常用心的把每次成績都記錄下來了。如果我要拿到小明同學最近5次的數學成績,應該怎麼定義資料格式?
首先回顧一下,在c的時代,資料型別有這麼幾類:
基本型別 | 構造型別 | 指標型別 | 空型別 |
---|---|---|---|
整型 short int long | 陣列 [] | 指標 * | void |
浮點型 float double | 結構體 struct | \ | |
\ | |||
字元型別 char | 共用體 union | \ | |
\ | |||
布林型別 bool (C99增加) | 列舉型別 enum | \ | |
\ |
用c語言有限的資料型別,要怎麼定義需要的資料呢?
char* name = "小明";
float scores[5] = {90,87,88.5,95,78};
看上去還不太複雜。\
再進一步想,如果實現一個c函式,由函式返回這些資料,怎麼辦?只能定義struct了。
//先宣告一個struct
struct name_scores {
char *name;
float scores[5];
};
//給struct賦值
struct name_scores xiaoming = {"小明" , {90,87,88.5,95,78}};
//函式返回型別是結構體
return xiaoming;
這個解決方案,看上去真是just so so。
到了c++的時代,似乎可以試試類的概念,把char*也換成string。
//先宣告一個類
class Student {
public:
string name;
float scores[5];
};
//例項化一個物件,賦值
Student xiaoming;
xiaoming.name = "小明";
xiaoming.scores = {90 ,87,88.5,95,78};
//函式中返回物件
return xiaoming;
然並卵,更麻煩了。
到了喬老爺子的時代,oc語言增加了NS開頭的基本資料類,NSString NSArray NSDictionary都是非常常用的,我們可以試著組合一下資料。
//儲存資料
NSString *name = @"小明";
NSArray *scores = @[@90,@87,@88.5,@95,@78];
NSDictionary *returnDic = @{@"name":name,@"scores":scores};
//返回字典
return returnDic;
這已經是最簡單的寫法,依然是比較複雜的形式。
所以,有沒有一種簡單的資料型別,可以輕鬆組合不同型別的資料?\
有!\
Swift的元組閃亮登場✨✨
//一行程式碼搞定
return ("小明",(90,87,88.5,95,78))
哇,只需一行程式碼,你買不了吃虧,買不了上當,元組就是這麼霸氣!\
有些人可能就不服氣了,陣列一樣可以這麼簡潔,為什麼不用陣列?客官請繼續看。
元組、陣列、字典,合適才是最好
首先說說字典,字典是key:value鍵值對,它適合將不同種類、不同用途的資料組合在一起,通過key值進行索引。
優點:
- 通過key值進行索引,查詢效率高
- 通過key值進行資料標註,可讀性高,易於區分多種資料
- key值唯一,增刪改可以保證資料唯一性
缺點:
- 一個value必須對應一個key,儘管有時不需要key
- key值順序不定,字典對key值表進行了hash,所以不方便儲存對順序敏感的資料
具體到小明的例子,資料格式如下
var name_score : Dictionary = ["name":"小明","scores":[90,87,88.5,95,78]]
我們試著讀取其中的資料
var name = name_score["name"] //列印值為Optional(小明)
var scores = name_score["scores"] //列印值為Optional((90,87,88.5,95,78))
而如果print(name_score)
,會發現輸出的key值順序發生了變化
字典輸出,觀察key值順序
接下來,我們再看看陣列。\
最早在c語言中,陣列用來儲存多個相同型別的資料,到了OC不再限定儲存資料的型別,Swift也沿用了OC的傳統。這也是小明的例子中爭議的來源,用陣列也可以解決問題呀。
那麼我們說說陣列的優缺點吧。
優點
- 資料儲存順序固定,增刪改也通過index來進行
- 集成了遍歷方法,適合對大量同類資料的處理
- 不需要定義key,寫法相對簡單
缺點
- 訪問特定資料時,查詢效率不高
- 處理特定資料時,需要牢記資料的index,可讀性不好,容易產生錯位處理
仍以小明為例
var name_score = ["小明",[90,87,88.5,95,78]]
訪問資料的方式如下
var name = name_score[0] //列印值為小明
var score = name_score[1] //列印值為(90,87,88.5,95,78)
我們print(name_score)
,可以看一下結果
陣列輸出,順序很重要
Swift已經對Array和Dictionary做了大量改良,非常方便使用。可是元組又可以為我們帶來什麼呢?
首先,當我們在Array中放置不同型別的資料時,我們無法再對每個資料的type做定義。\
["小明",[90,87,88.5,95,78]]可以被修改為[1,[90,87,88.5,95,78]],而1顯然不是正確的名字格式
\
而元組可以定義元素的型別\
var tuple : (String, Array) = ("小明",[90,87,88.5,95,78])
\
更深一步,元組巢狀元組每一個元素的型別都可以定義\
var tuple : (String, (Float,Float,Float,Float,Float)) = ("小明",(90,87,88.5,95,78))
其次,陣列的元素個數可能發生改變,我可以增加、刪除元素\
name_score.append("新增一個字串")
\
name_score.removeAtIndex(1)
\
而元組一旦定義,其元素個數確定,不能增加、刪除字典必須定義key,而元組不需要。當然,如有必要,你還可以為每個元素命名
var tuple = (name:"小明",[90,87,88.5,95,78])
\
tuple.name 等同於 tuple.0
字典的儲存順序不確定,而元組是固定的
通過上面幾個簡單的對比分析,我們發現,元組綜合了陣列、字典、甚至struct的一些優點,是對資料型別的一個強力補充。
下面分析一下元組的優缺點。
優點
- 元組可以同時儲存多種型別元素,且元素型別固定,以保證資料安全,除非你定義資料型別為Any。編譯器會對賦值引數型別進行檢查
- 元組的元素個數固定,不允許增加、刪除,編譯器會嚴格校驗賦值引數個數
- 無需定義key,但是必要時可以為資料命名,方便資料訪問
- 適合同時遍歷多元資料,例如官方文件的例子\
for (index, value) in shoppingList.enumerate()
缺點
- 不適合儲存大量資料,因為元組不支援append、remove等方法
- 考慮到工程實際情況,後端使用的語言可能不支援元組,需要轉換為其他格式
所以說,元組適合應用於組合少量的多元的資料,與陣列、字典結合使用可以產生強大威力。