---
# System prepended metadata

title: 'Lab05: 字典 、集合'
tags: [計算機概論]

---

# 字典 (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在將資料夾上傳