# 字典 (dictionary) - 跟串列類似,都是一種儲存資料的容器 - 字典內的元素是以鍵值對(key-value pairs)的形式存在,key是不能重複的。 - 字典的 key 需要是 [immutable(不可更改)](https://medium.com/starbugs/python-mutable-%E8%88%87-immutable-8ef7804181cd)且 hashable(唯一雜湊值 → 唯一)。 ![image](https://hackmd-prod-images.s3-ap-northeast-1.amazonaws.com/uploads/upload_ddd6588dde3b827fd16537597dc8d748.png?AWSAccessKeyId=AKIA3XSAAW6AWSKNINWO&Expires=1728194152&Signature=IERoA4ZPP3II4dz8hnIMVt1A8Yg%3D) - 字典 (dictionary)是基於[哈希表(Hash Table)](https://alrightchiu.github.io/SecondRound/hash-tableintrojian-jie.html)的資料結構。 ## 串列與字典的差異 | | list | dictionary | | -------- | -------- | -------- | | 表示方法 | list1 = [ 10, 20, 30 ] | dict1 = { "apple":10, "banana":20, "orange":30 } | | index | index從0開始分配,每個element都會到分配一個index。(順序性 sequential) | 以key-value為一組,使用key來查找value。 | | 插入及查找速度 | 插入及查找速度較慢 | 較快,"理論上"不會應為key增加而變慢 | | 占用的記憶體空間 | 較小 | 較大的記憶體空間 (空間換取時間) ## 建立一個空字典 ```python= #方法一 dict = {} print(dict) # 輸出:{} #方法二 dict = dict() print(dict) # 輸出:{} ``` ## 初始化一個字典 ```python= #dict = {key1:value1, key2:value2, ...} dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } print(dict) # 輸出:{'name': 'Bob', 'age': 18, 'ID': 'E12345678'} ``` 字典的key必須是唯一的,所以key必須是不可變的物件(Immutable Objects) 所以像是list、dictionary、set這類物件都不能當作key。 而value則沒有此限制 ```python= dict = { "name" : ["Bob", "Jim", "Jack"], "age" : [18, 20, 21], "ID" : ["E12345678", "D12345678", "C12345678"] } print(dict) # 輸出:{'name': ['Bob', 'Jim', 'Jack'], 'age': [18, 20, 21], 'ID': ['E12345678', 'D12345678', 'C12345678']} ``` value甚至可以是字典, ```python= dict = { "student1" : {"name" : "Bob", "age" : 18, "ID" : "E12345678"}, "student2" : {"name" : "Jim", "age" : 20, "ID" : "D12345678"}, } print(dict) # 輸出:{'student1': {'name': 'Bob', 'age': 18, 'ID': 'E12345678'}, 'student2': {'name': 'Jim', 'age': 20, 'ID': 'D12345678'}} ``` ## 字典的基本操作 - ### 查找 ```python= dict = { "name" : ["Bob", "Jim", "Jack"], "age" : [18, 20, 21], "ID" : ["E12345678", "D12345678", "C12345678"] } print(dict[name]) # 輸出:['Bob', 'Jim', 'Jack'] ``` - ### 新增元素 ```python= dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } dict["score"] = 90 print(dict) # 輸出:{'name': 'Bob', 'age': 18, 'ID': 'E12345678', 'score': 90} ``` - ### 修改元素 ```python= dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } dict["name"] = "Jack" print(dict) # 輸出:{'name': 'Jack', 'age': 18, 'ID': 'E12345678'} ``` - ### 刪除元素 ```python= dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } #dict[key] = value dict.pop("ID") print(dict) # 輸出:{'name': 'Bob', 'age': 18} ``` ## 字典的進階操作 1. `get()`方法 查到不存在的鍵值對時,返回None,而不是報錯。 ```python= dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } print(dict.get("score")) # 輸出:None ``` 1. `setdefault()`方法 查到不存在的鍵值對時,返回None,而不是報錯。 ```python= dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } print(dict.setdefault("score", 90)) #輸出:90 print(dict) #輸出:{'name': 'Bob', 'age': 18, 'ID': 'E12345678', 'score': 90} ``` 1. `keys()`方法 返回所有key的動態視圖 ```python= dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } print(dict.keys()) # 輸出:dict_keys(['name', 'age', 'ID']) ``` 2. `values()方法` 返回所有的value動態視圖 ```python= dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } print(dict.values()) # 輸出:dict_values(['Bob', 18, 'E12345678']) ``` 3. `update()方法` 批量新增、修改元素 ```python= dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } dict.update({"score" : 90, "major" : "ES", "age" : 20}) print(dict) # 輸出:{'name': 'Bob', 'age': 20, 'ID': 'E12345678', 'score': 90, 'major': 'ES'} ``` 5. `clear()方法` 清空字典 ```python= dict = { "name" : "Bob", "age" : 18, "ID" : "E12345678" } dict.clear() print(dict) # 輸出:{} ``` ## 更多的字典方法 dict1 = {"Bob":50, "Anna":80, "Jack":90} | 方法 | 意義 | 範例 |結果 | | -------- | -------- | -------- | -------- | |len(dict1) | 取得字典元素個數 | n=len(dict1)| n=3 | |dict1.copy()| 複製字典 | dict2= dict1.copy() | dict2 = {"Bob":50, "Anna":80, "Jack":90} | |鍵 in dict1 | 檢查鍵是否存在 | b="Bob" in dict1| b=True | # 集合(set) - 一個集合裡所有的鍵都不會重複,元素裡的內容可以是整數(int)、浮點數(float)、字串(string)、元組(tuple)、布林(boolen),但是不可以是串列(list)、字典(dict)、集合(set)。 - 因為集合不會包含重複的資料的特性,常用來進行去除重複的字元、或判斷元素間是否有交集、聯集或差集之類的關聯性。 ## 創建空集合 ```python fruits = set() print(fruits) # 輸出:{} ``` ## 創建集合 ```python fruits = set(["apple", "apple", "banana", "banana", "cherry"]) print(fruits) # 輸出:{'apple', 'banana', 'cherry'} ``` 或 ```python fruits = {"apple", "apple", "banana", "banana", "cherry"} print(fruits) # 輸出:{'apple', 'banana', 'cherry'} ``` ## 集合的基本操作 - 新增元素 ```python fruits = {"apple", "banana", "cherry"} fruits.add("orange") print(fruits) # 輸出:{'apple', 'orange', 'banana', 'cherry'} ``` - 刪除元素 ```python fruits = {"apple", "banana", "cherry"} fruits.remove("apple") print(fruits) # 輸出:{'banana', 'cherry'} ``` ## 集合的其他操作 1. clear()方法 清除集合 ```python fruits = {"apple", "banana", "cherry"} fruits.clear() print(fruits) # 輸出:set() ``` 2. copy()方法: 複製集合中的元素成為一個新的集合,可以避免破壞原始的集合 ```python fruit = {"apple", "banana", "cherry"} fruit_copy = fruit.copy() fruit_copy.add("orange") print(fruit) #輸出: {'cherry', 'apple', 'banana'} print(fruit_copy) #輸出: {'orange', 'cherry', 'apple', 'banana'} ``` 4. discard()方法: 刪除集合中指定的元素。若該指定的元素不存在也不會回傳KeyError。 ```python= fruit = {"apple", "banana", "cherry"} fruit.discard("orange") print(fruit) #輸出: {'banana', 'apple', 'cherry'} fruit.remove("orange") #輸出: KeyError ``` 5. update()方法: A.update(B),將集合B的元素加入集合A中。 ```python= A = {"apple", "banana", "cherry"} B = {"orange", "tomato"} A.update(B) print(A) #輸出: {'orange', 'tomato', 'cherry', 'apple', 'banana'} ``` ## 集合運算 ![image](https://hackmd-prod-images.s3-ap-northeast-1.amazonaws.com/uploads/upload_6e60c62b4033ee56e80f919419c9b892.png?AWSAccessKeyId=AKIA3XSAAW6AWSKNINWO&Expires=1728194221&Signature=OKYXDmU7KWWtXd7mTB2NjNLcQvs%3D) - 交集 ```python set1 = {"apple", "banana", "cherry"} set2 = {"banana", "cherry", "orange"} intersection = set1 & set2 print(intersection) # 輸出:{'banana', 'cherry'} ``` - 聯集 ```python set1 = {"apple", "banana", "cherry"} set2 = {"banana", "cherry", "orange"} union = set1 | set2 print(union) # 輸出:{'apple', 'banana', 'cherry', 'orange'} ``` - 差集 ```python set1 = {"apple", "banana", "cherry"} set2 = {"banana", "cherry", "orange"} difference = set1 - set2 print(difference) # 輸出:{'apple'} ``` - 對稱差集 ```python set1 = {"apple", "banana", "cherry"} set2 = {"banana", "cherry", "orange"} symmetric_difference = set1 ^ set2 print(symmetric_difference) # 輸出:{'apple', 'orange'} ``` - 子集 ```python set1 = {"apple", "banana"} set2 = {"apple", "banana", "cherry"} print(set1.issubset(set2)) # 輸出:True print(set2.issubset(set1)) # 輸出:False ``` - 超集 ```python set1 = {"apple", "banana"} set2 = {"apple", "banana", "cherry"} print(set1.issuperset(set2)) # 輸出:False print(set2.issuperset(set1)) # 輸出:Ture ``` > 參考: > [5. 資料結構— Python 3.11.10 說明文件](https://docs.python.org/zh-tw/3.11/tutorial/datastructures.html#sets) > [[Python教學] Dictionary 字典 和 Set 集合[Python教學]](https://utrustcorp.com/python_dictionary_set/) > <a href='https://blog.csdn.net/weixin_47906106/article/details/121772942'>详解Python字典的底层原理——哈希表(Python面试必备)</a> > <a href='https://www.cnblogs.com/jiakecong/p/15881370.html'>python字典底层原理</a> > <a href='https://blog.csdn.net/be5yond/article/details/120021250'>Python 深入理解dict---为什么 dict 查询元素比 list 快?</a> ## Lab05作業題目 - 繳交方式 :請到[https://140.116.179.59:8080](https://140.116.179.59:8080)完成作業題目,並將程式碼加上註解(你的理解),很重要,否則助教有權利扣你分數 - 禁止抄襲,否則助教會來查水表 - 題目為基本題3題+1題加分題,共4題 - Lab05_01( 30分 )、Lab05_02( 40分 )、Lab05_03( 30分 )==(不符規定九折,未註解七折,遲交六折)== - 加分題直接列入期末成績計算 - github檔名格式: - 每一個檔案為:Lab05_OO.py - 所有檔案放入資料夾學號_Lab05在將資料夾上傳