<style>
.new {
color: red;
font-weight: bold;
}
</style>
# String
資訊之芽 熊育霆 2022/03/27
---
## 在開始之前
----
### 肌肉記憶 Muscle Memory
等等中間會不時穿插一些練習時間
把每個範例在你的電腦上照著打一遍,善用你的肌肉記憶把 python 的語法記熟
(實作比抄筆記還要有用許多)
---
## Recall: what are strings?
我們來複習第一週教過的東西
----
一段文字
```python=
print(type("Hello, world!")) # <class 'str'>
```
----
可以用單引號或雙引號包起來
```python=
"bing chilling" # 用雙引號包起來
'bing chilling' # 用單引號包起來
```
----
加法(串接)、乘法(重複接)
```python=
name = "Madoka"
print("Hello, " + name) # Hello, Madoka
print(name * 3) # MadokaMadokaMadoka
```
----
跳脫字元,例如 `\n`, `\'`
```python=
print('Hello. It\'s me.') # Hello. It's me.
print('Never gonna give you up', 'Never gonna let you down', 'Never gonna run around and desert you', sep='\n')
"""Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
"""
```
----
多行字串
```python=
print("""這幾行
會被
印出來 :)""")
```
----
f-string
```python=
name = "Kira Yoshikage"
age = 33
print("name=", name, "age=", age)
print(f"name={name} age={age}")
print(f"{name=} {age=}")
```
----
Questions?
![](https://thumbs.gfycat.com/AllPersonalKingsnake-size_restricted.gif)
---
## 名詞解釋:字元 char
字元:一個字
```python=
'a'
'b'
'c'
```
字串:由一串字元組成
---
## 補充:Python 沒有 char
在 C, C++, Java 等程式語言中有 char (字元) 資料型別,但在 Python 中沒有 char 資料型別,只有長度為 1 的字串。
```c=
char c = 'a'; // C/C++
```
```python=
c = 'a' # Python
# or
c = "a"
print(type(c))
```
---
## 跟 `list` 差不多一樣的地方
Bing Chilling!
----
![](https://c.tenor.com/XVZlONPlQUIAAAAd/binchiling-john-cena.gif)
----
### 加法和乘法運算
加法(串接)、乘法(重複接)
```python=
name = "Madoka"
print("Hello, " + name) # Hello, Madoka
print(name * 3) # MadokaMadokaMadoka
```
上週教了 `list` ,其實 `list` 也有對應的操作
```python=
print(['c'] + [8, 7] + [6, 3]) # ['c', 8, 7, 6, 3]
print([8, 7] * 3) # [8, 7, 8, 7, 8, 7]
```
----
### 比較運算
兩字串是否相等
```python=
print("abc" == "abc") # True
print("abc" != "abc") # False
```
比較兩字串字典序
```python=
print("abc" < "abd") # True
print("abc" < "abcd") # True
print("abc" > "def") # False
```
有點難很簡短的解釋什麼是字典序,大家可以看一下[這個](https://en.wikipedia.org/wiki/Alphabetical_order#Ordering_in_the_Latin_script),簡單來說就是從頭比到尾、都一樣比長度
----
### `in`, `not in`
```python=
text = 'abc'
print('a' in text) # True
print('ab' in text) # True
print('ac' in text) # False
print('ac' not in text) # True
```
----
### `len`
```python=
zhang_xina = "早上好中國"
print(zhang_xina)
print(len(zhang_xina)) # 5
```
----
### 取第 i 個
```python=
zhang_xina = "早上好中國"
print(zhang_xina[0]) # 早
print(zhang_xina[1]) # 上
print(zhang_xina[3]) # 中
print(zhang_xina[-1]) # 國
print(zhang_xina[5]) # IndexError: string index out of range
```
可以試試 `zhang_xina = ["早", "上", "好", "中", "國"]`
----
### Slicing
```python=
zhang_xina = "早上好中國"
print(zhang_xina[2:4]) # 好中
print(zhang_xina[:3]) # 早上好
print(zhang_xina[2:]) # 好中國
print(zhang_xina[::-1]) # 國中好上早
print(zhang_xina[:-3:-1]) # 國中
```
可以試試 `zhang_xina = ["早", "上", "好", "中", "國"]`
----
### 可迭代 Iterable
如果你忘記什麼是 iterable,就是一句話:可以 for 它
```python=
zhang_xina = "早上好中國"
for word in zhang_xina:
print(word)
"""早
上
好
中
國
"""
```
----
Questions?
早上好資訊之芽,現在我有 list,我很喜歡 list ...
---
## 小補充 iterable
[還不錯的教學文件](https://www.pythonlikeyoumeanit.com/Module2_EssentialsOfPython/Iterables.html)
我們來看一下 definition 和一些花式用法
---
## 跟 list 不一樣的地方
----
### Immutable 不能改值
```python=
text = "abcde"
text[2] = 'f'
# TypeError: 'str' object does not support item assignment
```
----
如果要改掉某個字的話只能很費工地這樣做
```python=
text = "abcde"
new_text = text[:2] + "f" + text[3:]
print(new_text) # abfde
```
----
為什麼要這樣設計呢?我也很好奇。於是我找到了[這篇問答](https://stackoverflow.com/questions/8680080/why-are-python-strings-immutable-best-practices-for-using-them),大家有興趣可以看看。不過你們需要知道更多才比較能體會這樣設計的好處。
簡單來說就是,恩,dict 和 hash 之類的?你下半堂課就會知道這些東西了
----
沒有 immutability 的話可能會發生一些怪事
```python=
a = [8, 7, 6, 3]
b = a
a[2] = 5
print(f"{a=}") # a=[8, 7, 5, 3]
print(f"{b=}") # b=[8, 7, 5, 3]
# Remark: use id
print(f"{id(a)=}")
print(f"{id(b)=}")
```
回憶一下為何我們會看到 a, b 會同時被改值
這是因為他們 reference 到同一個物件
----
[Why is immutability so important (or needed) in JavaScript?](https://stackoverflow.com/questions/34385243/why-is-immutability-so-important-or-needed-in-javascript)
雖然不是 Python 但是核心精神差不多,可以參考看看
----
Questions?
----
課間練習:輸入一行字,輸出第$i$行把第$i$個字元取代成`*`後印出,詳見範例
Input:
```txt
abcdefg
```
Output:
```txt
*bcdefg
a*cdefg
ab*defg
abc*efg
abcd*fg
abcde*g
abcdef*
```
---
## String 的各種操作 (method)
----
String 的操作有[這麼多](https://www.w3schools.com/python/python_ref_string.asp),當然我只會講常用的那幾個
----
如果你想知道有沒有什麼偷吃步的方法達成你想要做的事情,就把這件事拿去餵狗
比如說你可以試著把以下這些東西拿去 google
* Python turn string uppercase (把每個字元轉成大寫)
* Python string first capital (把第一個字轉成大寫)
* Python string remove blank (把空白拿掉)
Google 不會笑你的英文,所以隨便打都沒差
---
### replace
```python=
lyrics = """Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
"""
modified_lyrics = lyrics.replace("Never", "Always")
print(modified_lyrics)
print(lyrics)
```
----
就是搜尋與取代
注意:原本的字串不會被改動
更多可以參考[這裡整理的懶人包](https://www.w3schools.com/python/ref_string_replace.asp)
----
**所以...現在是練習時間**
1. 把前面範例中的 "gonna" 取代成 "wanna"
2. 把前面範例中的 "gonna" 取代成 "wanna",並且把 "you" 取代成 "me"
---
### isdigit & isalpha & isalnum
判斷字串中是否全為數字/字母/數字與字母
----
```python=
print("119".isdigit()) # True
print("Hello".isalpha()) # True
print("Hello, it's me".isalpha()) # False
print("C8763".isalnum()) # True
```
----
當然,我們可以不用 `isdigit` 暴力做到這些事情
```python=
s = "271828"
flag = True
for ch in s:
if not "0" <= ch <= "9":
# if ch not in "0123456789":
flag = False
print(flag)
```
但這樣很累欸
----
當然還有很多其他的 is 家族,你們可以自己慢慢看,不用背
----
Questions?
----
**所以...現在是練習時間**
搭配 `isdigit` 和 `len` 判斷一串數字是否為合法的手機號碼
1. 十個數字
2. 前兩位是 09
```python=
text = input()
# 請開始你的練習
```
---
### strip
```python=
new_text = " aaaaa ".strip()
print(f"{new_text=}") # new_text='aaaaa'
```
把字串頭尾的空白拿掉,並且回傳新的字串
----
沒錯,就這樣
你們可以想一下,你瀏覽的網站中哪些地方會用到這個功能
Questions?
---
### lower & upper
將字串中的英文字母全變成小寫或大寫
```python=
print("Ko no Dio da!".upper()) # KO NO DIO DA!
print("Ko no Dio da!".lower()) # ko no dio da!
```
----
一些使用情境:不分大小寫搜尋某個字串,例如說
```python=
want_to_search = "Iso"
text = "Isometry, isomorphism, isolated"
text.lower().find(want_to_search.lower()) # 下一小節是 find
```
這可以搭配後面的其他東西做練習
---
### find
尋找
```python=
lyrics = """Never gonna give you up"""
print(lyrics.find("gonna")) # 6
```
----
用法
```python=
string.find(value, start, end)
```
* value: 欲尋找的東東
* start: 從哪裡開始找,預設是 0
* end: 找到哪裡結束,預設是到字串結尾
----
把所有 gonna 找到
```python=
lyrics = """Never gonna give you up
Never gonna let you down
Never gonna run around and desert you
"""
positions = []
start = 0
value = "gonna"
while True:
ret = lyrics.find(value, start)
if ret == -1:
break
positions.append(ret)
start = ret + len(value)
print(positions)
```
----
Questions?
---
### split
把字串切成一堆字串用 list 包起來
```python=
text = "Never gonna give you up"
splitted = text.split()
print(splitted) # ['Never', 'gonna', 'give', 'you', 'up']
```
----
什麼時候會用到?
很多時候
----
範例:計算你輸入了幾個英文單字
```python=
words = input().split()
print(len(words))
```
----
範例:計算一堆數字的平均
```python=
numbers = list(map(float, input().split()))
print(sum(numbers) / len(numbers))
```
----
更詳細的用法
```python=
string.split(separator, maxsplit)
```
`separator`: 用什麼來切,預設是空白
`maxsplit`: 最多切幾個
可以參考 [w3school](https://www.w3schools.com/python/ref_string_split.asp) ,但我是沒用過那兩個參數幾次啦
----
人肉直譯器練習
猜猜看以下的東西會印出什麼,猜完之後在自己的電腦上跑跑看
```python=
a = "1 2 3 4 5".split()
b = "1 2 3 4 5".split(' ')
c = "1 2 3 4 5".split('3')
print(f"{a=}\n{b=}\n{c=}")
```
`split()` 和 `split(' ')` 其實有一些微妙的差異,細節需要注意一下
----
比如說
這段程式碼
```python
d = list(map(int, "1 2 3 4 5".split(' ')))
```
會噴錯
```python
ValueError Traceback (most recent call last)
/tmp/ipykernel_409726/410874544.py in <module>
----> 1 d = list(map(int, "1 2 3 4 5".split(' ')))
ValueError: invalid literal for int() with base 10: ''
```
因為空字串不能被轉成 `int`
----
下面這個就不會出事
```python
d = list(map(int, "1 2 3 4 5".split()))
```
----
Questions?
---
### join
把一堆用 list 包起來的字串合成一個字串
```python=
words = ['Never', 'gonna', 'give', 'you', 'up']
print(' '.join(words)) # Never gonna give you up
```
就是把 split 反過來
----
用法
```python
string.join(iterable)
```
用 `string` 把 `iterable` 裡面的東西全部接起來
`iterable` 裡面必須是一些字串
----
人肉直譯器練習
有些是會噴錯的
要看答案的話複製到自己的電腦上跑跑看
```python
''.join([1, 2, 3])
```
```python
''.join(['1', '2', '3'])
```
```python
''.join(map(str, range(10)))
```
```python
', '.join(map(str, range(10)))
```
----
Questions?
---
這麼多誰背的完阿?
對阿很少人會特地去記這些東西,如果你想要達成什麼目的,就把你想做的事情拿去餵 google 看看
---
## 綜合練習
有時間的話我應該現場寫一下
----
計算一個英文句子中有幾個字
例如 "Hello, it's me." 有三個, "Never gonna give you up" 有五個字
----
判斷一個字是否是回文
例如 "ada", "racecar" 是,"sprout" 不是
----
可以在 [LeetCode](https://leetcode.com/tag/string/) 找些簡單題來玩玩
----
Questions?
---
## 作業
[3109](https://neoj.sprout.tw/problem/3109/)
[3040](https://neoj.sprout.tw/problem/3040/)
[3046](https://neoj.sprout.tw/problem/3046/)
---
End
---
## 參考解答們
----
```python=
text = input()
for i in range(len(text)):
print(text[:i] + '*' + text[i+1:])
```
----
### replace
```python=
new_lyrics = lyrics.replace("gonna", "wanna")
```
```python=
new_lyrics = lyrics.replace("gonna", "wanna").replace("you", "me")
```
----
### isdigit & isalpha & isalnum
```python=
text = input()
print(len(text) == 10 and text[:2] == "09" and text.isdigit())
```
{"metaMigratedAt":"2023-06-16T21:13:17.690Z","metaMigratedFrom":"YAML","title":"String","breaks":true,"slideOptions":"{\"transition\":\"fade\"}","contributors":"[{\"id\":\"f93c8d2e-91fa-44cf-b9d2-ea6d875fcb79\",\"add\":10316,\"del\":676}]"}