# 資研 12/29 社課講義
[**提問表單**](https://forms.gle/z4dPC1JPV6uA2q9w7)
---
## 集合 Set

[圖源](https://steam.oxxostudio.tw/category/python/basic/set.html)
### 函式
| 函式用法 | 用途 |
|:------------------------------------------:|:--------------------------------------------------------------------------------------------------------:|
| `Set.add(element)` | 加入 element |
| `Set_a.union(Set_b)` | 回傳 Set_a 和 Set_b 的所有元素(a聯集b,`a∪b`/`a\|b`) |
| `Set_a.update(Set_b)` | 將 Set_b 所有元素併入 Set_a(a聯集b,`a∪b`/`a\|b`) |
| `Set.remove(element)` | 刪去 element |
| `Set.discard(element)` | 刪去 element |
| `Set.pop()` | 刪去 Set 內隨機一個元素 |
| `Set.clear()` | 刪去 Set 內所有元素 |
| `del Set` | 刪去 Set |
| `Set_a.difference(Set_b)` | 回傳在 Set_a 中但不在 Set_b 中的元素(a差集b,a-b) |
| `Set_a.difference_update(Set_b)` | 刪除 Set_a 中和 Set_b 中一樣的元素(a差集b,a-b) |
| `Set_a.intersection(Set_b, Set_c)` | 回傳同時存在於在 Set_a、Set_b、Set_c 中的元素(abc的交集,`a∩b∩c`/`a&b&c`) |
| `Set_a.intersection_update(Set_b, Set_c)` | 刪除 Set_a 中和 Set_b、Set_c 不一樣的元素(abc的交集,`a∩b∩c`/`a&b&c`) |
| `Set_a.isdisjoint(Set_b)` | 若 Set_a 和 Set_b 完全不相同則回傳 True |
| `Set_a.issubset(Set_b)` | 回傳 Set_a 的所有元素是否存在於 Set_b 中(a屬於b,`a∈b`) |
| `Set_a.issuperset(Set_b)` | 回傳 Set_b 的所有元素是否存在於 Set_a 中(b屬於a,`b∈a`) |
| `Set_a.symmetric_difference(Set_b)` | 回傳 Set_a、Set_b 中除了2者都有的的所有元素(a對稱差集b,`a△b` or `a⊕b`/`a^b`) |
| `Set_a.symmetric_difference_update(Set_b)` | 刪除 Set_a 中和 Set_b 一樣的元素,加入 Set_b 中和 Set_a 不一樣的元素(a對稱差集b,`a△b` or `a⊕b`/`a^b`) |
| `Set.copy()` | 回傳 Set 的複製品 |
>其中Set表**集合名稱**,element表**元素**
```python=
# difference
S1 = {1, 2, 3, 4, 5}
S2 = {2, 4, 6, 8, 10}
S3 = S1.difference(S2)
print(S3) # print(S1.difference(S2))
# 輸出:{1, 3, 5}
# difference_update
S1 = {1, 2, 3, 4, 5}
S2 = {2, 4, 6, 8, 10}
S1.difference_update(S2)
print(S1)
# 輸出:{1, 3, 5}
# intersection
S1 = {1, 2, 3, 4, 5}
S2 = {2, 4, 6, 8, 10}
S3 = S1.intersection(S2)
print(S3) # print(S1.intersection(S2))
# 輸出:{2, 4}
S1 = {1, 2, 3, 4, 5}
S2 = {2, 4, 6, 8, 10}
S3 = {2, 3, 6, 9}
S4 = S1.intersection(S2, S3)
print(S4) # print(S1.intersection(S2, S3))
# 輸出:{2}
# intersection_update
S1 = {1, 2, 3, 4, 5}
S2 = {2, 4, 6, 8, 10}
S1.intersection_update(S2)
print(S1)
# 輸出:{2, 4}
S1 = {1, 2, 3, 4, 5}
S2 = {2, 4, 6, 8, 10}
S3 = {2, 3, 6, 9}
S1.intersection_update(S2, S3)
print(S1)
# 輸出:{2}
# isdisjoint
S1 = {1, 2}
S2 = {1, 2, 3, 4, 5}
print(S1.isdisjoint(S2))
# 輸出:False
# issubset
S1 = {1, 2}
S2 = {1, 2, 3, 4, 5}
print(S1.issubset(S2))
# 輸出:True
# issuperset
S1 = {1, 2}
S2 = {1, 2, 3, 4, 5}
print(S1.issuperset(S2))
# 輸出:False
# symmetric_difference
S1 = {1, 2, 3, 4, 5}
S2 = {2, 4, 6, 8, 10}
S3 = S1.symmetric_difference(S2)
print(S3) # print(S1.intersection(S2))
# 輸出:{1, 3, 5, 6, 8, 10}
# symmetric_difference_update
S1 = {1, 2, 3, 4, 5}
S2 = {2, 4, 6, 8, 10}
S1.symmetric_difference_update(S2)
print(S1)
# 輸出:{1, 3, 5, 6, 8, 10}
# copy
S = {'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'}
S_ = S.copy()
print(S_)
# 輸出:{'Tuesday', 'Monday', 'Thursday', 'Friday', 'Wednesday'}
```
:::warning
- 只有intersection可同時比較2個以上的集合
:::
---
## 字典 Dictionaries
:::warning
**容器**
| List | Tuple | Set | Dictionary |
|:--------:|:----------:|:----------:|:----------:|
| 有序 | 有序 | **無序** | 有序 |
| 資料可變 | **資料不可變** | **資料不可變** | 資料可變 |
:::
### 宣告字典
- 字典表示方法:`{key : value}`
```python=
D = {'fruit_a': 'apples', 'fruit_b': 'bananas'}
D = dict(fruit_a= 'apples', fruit_b= 'bananas')
```
- 字典內可放置**多個元素**
- 利用 `dict()` 將其他資料型態轉為字典
>key須以變數表示(命名規則與變數相同)
- 一個key對應一個value,若有2個或以上value與之相對應,則以後者為準
- 字典內之元素**不限於單一資料型態**
>數字、字串、布林值、列表皆可置於字典內(value)
>key:僅限於string
```python=
# 有2個或以上value與之相對應以後者為準
D = { 'Monday': 1,
'Tuesday': 2,
'Wednesday': 3,
'Thursday': 4,
'Thursday': 5}
print(D)
# 輸出:{'Monday': 1, 'Tuesday': 2, 'Wednesday': 3, 'Thursday': 5}
# 不限於單一資料型態
D = {'one': 1, 'two': True, 'three': '三', 'four': [1, 2, 3, 4]}
print(D)
# 輸出:{'one': 1, 'two': True, 'three': '三', 'four': [1, 2, 3, 4]}
```
### 取得資料
#### <font color='#004B97'>**取得整個列表**</font>
1. 印出整個字典
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
print(D)
# 輸出:{'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五': 5}
```
2. 函式:`Dict.items()`
>每一對key & value組成一個Tuple,由各個Tuple組成一個List
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
x = D.items()
print(x, type(x), sep='\n')
# 輸出:dict_items([('一', 'one'), ('二', 'Two'), ('三', 3), ('四', 'Four'), ('五', 5)])
# <class 'dict_items'>
```
#### <font color='#004B97'>**取得key**</font>
1. 取得所有的key;函式:`Dict.keys()`
>以List回傳所有的key值
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
x = D.keys()
print(x, type(x), sep='\n')
# 輸出:dict_keys(['一', '二', '三', '四', '五'])
# <class 'dict_keys'>
```
#### <font color='#004B97'>**取得value**</font>
1. 取得單一一個value;語法:`Dict[key]`
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
print(D['二'])
# 輸出:Two
```
2. 取得單一一個value;語法:`Dict.get(key)`
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
print(D.get('二'))
# 輸出:Two
```
3. 取得value;語法:`Dict.setdefault(key, value)`
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
print(D.setdefault('一', '2'))
# 輸出:one
```
4. 取得所有的value;函式:`Dict.values()`
>以List回傳所有的value值
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
x = D.values()
print(x, type(x), sep='\n')
# 輸出:dict_values(['one', 'Two', 3, 'Four', 5])
# <class 'dict_values'>
```
:::warning
**比較**
`Dict[key]` & `Dict.get(key)` & `Dict.setdefault(key, value)`
- []:當該key不存在時會報錯
- get() & setdefault():當該key不存在時不會報錯
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
print(D['1'])
```
```
KeyError Traceback (most recent call last)
<ipython-input-53-2a44e213f754> in <cell line: 4>()
2 D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
3
----> 4 print(D['1'])
KeyError: '1'
```
:::
### 判斷是否存在
- 使用`in`
>To determine if a specified key is present in
>僅用於判斷"key"是否存在於字典中
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
print(('一' in D), (3 in D))
# 輸出:True False
```
### 更改資料
#### <font color='#004B97'>**修改**</font>
1. 使用`=`,直接修改
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D['一'] = 11
print(D)
# 輸出:{'一': 11, '二': 'Two', '三': 3, '四': 'Four', '五': 5}
```
2. 使用函式:`Dict.update({key: value})`
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D.update({'一': 111111})
print(D)
# 輸出:{'一': 111111, '二': 'Two', '三': 3, '四': 'Four', '五': 5}
```
#### <font color='#004B97'>**添加**</font>
1. 使用`=`,直接添加
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D['六'] = 'six'
print(D)
# 輸出:{'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五': 5, '六': 'six'}
```
2. 使用函式:`Dict.update({key: value})`
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D.update({'六': 6})
print(D)
# 輸出:{'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五': 5, '六': 6}
```
:::warning
使用`=`直接賦值與使用`update`函式時,若
該key**已有**相對應value => **更改**現有value
該key**未有**相對應value => **新增**進入字典
:::
#### <font color='#004B97'>**刪除**</font>
1. 刪除所指定key的該項資料;使用函式:`Dict.pop(key)`
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D.pop('一')
print(D)
# 輸出:'二': 'Two', '三': 3, '四': 'Four', '五': 5}
```
2. 刪除隨機一項資料;使用函式:`Dict.popitem()`
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D.popitem()
print(D)
# 輸出:{'一': 'one', '二': 'Two', '三': 3, '四': 'Four'}
```
3. 刪除所指定key的該項資料;使用函式:`del Dict[key]`
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
del D['一']
print(D)
# 輸出:{'二': 'Two', '三': 3, '四': 'Four', '五': 5}
```
4. 清除該字典內的所有資料;使用函式:`Dict.clear()`
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D.clear()
print(D)
# 輸出:{}
```
:::warning
在下列程式碼中,x的值為D之value,所以一旦D的值有所改變,x也會隨之變化
>其他會改變字典值的,同理
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
x = D.values()
print(x)
D["一"] = "white"
print(x)
# 輸出:dict_values(['one', 'Two', 3, 'Four', 5])
# dict_values(['white', 'Two', 3, 'Four', 5])
```
:::
### 複製字典
法一
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D_ = D
```
法二
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D_ = D.copy()
```
法三
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
D_ = dict(D)
```
### 迭代
#### <font color='#004B97'>**items**</font>
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
for i in D.items():
print(i)
# 輸出:('一', 'one')
# ('二', 'Two')
# ('三', 3)
# ('四', 'Four')
# ('五', 5)
```
#### <font color='#004B97'>**keys**</font>
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
for i in D.keys():
print(i)
# 輸出:一
# 二
# 三
# 四
# 五
```
#### <font color='#004B97'>**values**</font>
```python=
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
for i in D.values():
print(i)
# 輸出:one
# Two
# 3
# Four
# 5
```
### 巢狀字典 Nested Dictionaries
:::warning
**巢狀迴圈 Nested Loop**
- 雙重迴圈(迴圈中的迴圈)
- **記得使用不同變數**
```python=
# 印出"九九乘法表"
for i in range(1, 10):
for j in range(1, 10):
print(f'{i}*{j}={i*j}', end='\t')
print()
```
:::
宣告法一
```python=
Members = {
'num_1':{
'age': 17,
'birth': '一月三十日'
},
'num_2':{
'age': 18,
'birth': '四月十日'
}
}
print(Members['num_1']['age'])
# 輸出:17
```
宣告法二
```python=
num_1 = {
'age': 17,
'birth': '一月三十日'
}
num_2 = {
'age': 18,
'birth': '四月十日'
}
Members = {
'num_1': num_1,
'num_2': num_2
}
print(Members['num_1']['age'])
# 輸出:17
```
### 函式
| 函式寫法 | 用途 |
|:---------------------------:|:------------------------------:|
| `Dict.items()` | 取得整個列表 |
| `Dict.keys()` | 取得所有key |
| `Dict.get(key)` | 取得所指定key的value |
| `Dict.values()` | 取得所有value |
|`Dict.setdefault(key1, key2)`|回傳所指定key的value(可同時回傳多個)|
| `Dict.update({key: value})` | 更改、新增字典中的資料 |
| `Dict.pop(key)` | 刪除所指定key的該項資料 |
| `Dict.popitem()` | 刪除隨機一項資料 |
| `del Dict[key]` | 刪除所指定key的該項資料 |
| `Dict.clear()` | 清除該字典內的所有資料 |
| `len(Dict)` | 回傳該字典的長度 |
| `dict.fromkeys(x, y)` | 回傳一個字典其key為x,value為y |
```python=
# len
D = {'一': 'one', '二': 'Two', '三': 3, '四': 'Four', '五':5}
print(len(D))
# 輸出:5
# fromkeys
x = ['Tom', 'Cindy', 'Chris'] # 可以是tuple也可以是list
y = 60
D = dict.fromkeys(x, y) # 此時的dict為函式必須,非字典名稱
print(D)
# 輸出:{'Tom': 60, 'Cindy': 60, 'Chris': 60}
```
### 排序
1. 直接排序
>依照key去排序(ASCII碼)
法一
```python=
D = {
'Sam': 95,
'Molly': 80,
'Albert': 80,
'Cindy': 65,
'Sally': 20
}
print(sorted(D))
# 輸出:['Albert', 'Cindy', 'Molly', 'Sally', 'Sam']
```
法二
```python=
D = {
'Sam': 95,
'Molly': 80,
'Albert': 80,
'Cindy': 65,
'Sally': 20
}
print(sorted(D.keys()))
# 輸出:['Albert', 'Cindy', 'Molly', 'Sally', 'Sam']
```
法三
```python=
D = {
'Sam': 95,
'Molly': 80,
'Albert': 80,
'Cindy': 65,
'Sally': 20
}
print(sorted(D.items()))
# 輸出:[('Albert', 80), ('Cindy', 65), ('Molly', 80), ('Sally', 20), ('Sam', 95)]
```
2. 使用value來排序
:::warning
**lambda**
- 小型的自訂義函式(?
- 語法:
```python=
x = lambda a, b: a**b
print(x(2, 5))
```
:::
```python=
# 依value排序_由高到低
D = {
'Sam': 95,
'Molly': 80,
'Albert': 80,
'Cindy': 65,
'Sally': 20
}
print(sorted(D.items(), key=lambda x:x[1]))
# 輸出:[('Sally', 20), ('Cindy', 65), ('Molly', 80), ('Albert', 80), ('Sam', 95)]
```
```python=
# 依value排序_由低到高
D = {
'Sam': 95,
'Molly': 80,
'Albert': 80,
'Cindy': 65,
'Sally': 20
}
print(sorted(D.items(), key=lambda x:-x[1]))
# 輸出:[('Sam', 95), ('Molly', 80), ('Albert', 80), ('Cindy', 65), ('Sally', 20)]
```
```python=
# 依value排序_先按value降冪,若相同再按key升冪
D = {
'Sam': 95,
'Molly': 80,
'Albert': 80,
'Cindy': 65,
'Sally': 20
}
print(sorted(D.items(), key=lambda x:(-x[1], x[0])))
# 輸出:[('Sam', 95), ('Albert', 80), ('Molly', 80), ('Cindy', 65), ('Sally', 20)]
```
---
## 練習題
**Zerojudge**
[**連結**](https://zerojudge.tw/)
---
## 補充資料
**推薦網站:**[**W3Schools**](https://www.w3schools.com/)