#!/usr/bin/env python
# coding: utf-8
#
#
# Open In Jupyter nbviewer
#
#
#
# [](https://colab.research.google.com/github/twMr7/Python-Machine-Learning/blob/master/04-String_Operations.ipynb)
#
#
# # 4. `str` 字串操作
#
# `str` 字串是以字元為元素的序列資料結構,字串的語法使用單引號或雙引號包起來,一樣的引號要成對使用。
#
# 元素內容是按照儲存順序的 index 存取,語法為 **`[ index ]`**。 如果按照由前往後的順序,**第一個元素 index 是0**,依次往後遞增; 如果反過來由後往前存取,**最後一個元素 index 可以用-1**,依次向前遞減。
#
# | 字串範例 | 說明 |
# |------------------------------|-----------------------------------------------|
# | `''` | 空字串 |
# | `"Python's"`, `'Python"s'` | 字串用單引號或雙引號包起來 |
# | `'Python\'s\n'` | 特殊字元前面要加反斜線 `\` |
# | `r'c:\Users\name'` | 引號前置碼`r`保留字串呈現的原貌(raw string) |
# | `"This" "is" "concatenated"` | 相鄰的字串會自動被串接起來 |
#
# - 內建函式 `str()` 用來建構新字串,或將物件轉成字串。
# - 內建函式 `hex()`、`bin()` 分別可以用來將數值轉換成十六進位及二進位的數字字串。
# - 內建函式 `chr()` 可以用來將字碼轉換成對應的字元,是 `ord()` 的逆向操作。
# - 內建函式 `len()` 可以用來回傳字串的長度。
# - 內建函式 `print()` 可以用來將字串內容輸出至畫面。
#
# 字串類別本身有很多專屬的方法,請參閱官方文件 [Text Sequence Type — str](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str)。以下僅列出常用的幾個:
# - `format()` 用來格式化字串。
# - `count()` 計算某個子字串出現幾次。
# - `find()` 找出子字串出現的位置。
# - `lower()` 返回全部是小寫的複本。
# - `upper()` 返回全部是大寫的複本。
# - `replace()` 將子字串全部替換成指定的字串。
# - `split()` 將字串按照指定的分隔符號切割。
# - `strip()` 移除字串前後的空白字元。
#
# 字串也是序列容器,所以一般 immutable 序列容器的共同方法也都可以用,參閱官方文件 [Common Sequence Operations](https://docs.python.org/3/library/stdtypes.html#common-sequence-operations)。
#
# ### § 字串是不能就地變更的序列容器。
#
# 字串在建立後,元素內容**不可以**就地變更(immutable)。
# In[1]:
# 對字串元素指定新值會造成錯誤
s = 'Pithon'
s[1] = 'y'
# ### § 透過切割、重複複製、及串接的操作可以產生新字串。
# In[2]:
# 使用 [from:to:interval] 的語法切割片段範圍
# 使用加號 '+' 串接字串
s = s[0] + 'y' + s[2:]
print(s)
# In[3]:
# 使用乘號 '*' 重複複製序列元素
s = 3 * (s + ' ') + 'rocks!'
print(s)
# ### § 讀取某位置的索引值不能超過範圍,但片段的指定可以容許超過範圍。
# In[4]:
print('length of string is ' + str(len(s)))
# 超出索引值範圍會造成錯誤
s[60]
# In[5]:
# 指定的片段不存在返回空字串
s[21:60]
# ### § 字串類別本身有許多好用的方法,可以用來操作子字串
# In[6]:
# 數一數字串裡有幾個空格字元
print('There are ' + str(s.count(' ')) + ' spaces')
# In[7]:
# 將空格字元用逗號取代
s = s.replace(' ', ',')
print('New comma separated string is: ' + s)
# In[8]:
# 將逗號分隔的片段切割成子串
print(s.split(sep = ','))
# ## 4.1 用 `format()` 格式化字串
# 使用大括號 `{` `}` 保留需要格式化字串的位置,裡面可以指定欄位名稱及格式規則。(註: 以下格式是簡化過的版本,完整的定義請參閱官方文件 [6.1.3. Format String Syntax](https://docs.python.org/3/library/string.html#format-string-syntax))
#
#
格式化語法: `{` `欄位名稱` `:格式規則` `}`
#
#
# - `欄位名稱`:可以用數字或文字命名。欄位名字所在的位置,會被指定用某個格式化後的文字取代。
# - `格式規則`:指定用來從原物件資料轉成字串的規則,如欄位寬、小數點位數、左右對齊等。格式的規則按照以下語法順序指定,中括號不是語法的一部份,只是用來區隔每一種可有可無的格式選項:
#
#
#
格式規則順序: [[`空白填補字元`]`對齊`] [`#`] [`0`] [`寬度`] [`.小數點精度`] [`格式類型`]
#
#
# - `對齊`
#
# | 對齊選項 | 說明 |
# |-----------|-----------|
# | **`<`** | 靠左對齊 |
# | **`>`** | 靠右對齊 |
# | **`^`** | 置中 |
#
# - `#`:指定顯示數值進制的前綴符號。
# - `0`:針對數值格式,指定在空白處補 `'0'`。
# - `寬度`:指定欄位寬。
# - `.小數點精度`:指定小數點後面幾位數
# - `格式類型`
#
# | 格式類型 | 說明 |
# |-----------|-----------|
# | **`s`** | 字串 |
# | **`c`** | 字元 |
# | **`b`** | 二進位 |
# | **`d`** | 十進制整數 |
# | **`x`** | 小寫字母十六進制整數 |
# | **`X`** | 大寫字母十六進制整數 |
# | **`f`** | 浮點數,預設小數點以下6位 |
# | **`e`** | 小寫字母科學記號 |
# | **`E`** | 大寫字母科學記號 |
# | **`%`** | 將浮點數轉換為百分比 |
# ### § `format` 指定欄位名稱
# In[9]:
import math
# 用數字指定欄位名字,數字對應的是format()裡的參數順序
print('Math constants: π = {0}, e = {1}, τ = {2}'.format(math.pi, math.e, math.tau))
# In[10]:
# 欄位可以重複指定使用
print('Math constants: π = {0},\n τ = {1}, \tτ 其實就是 2π = 2 * {0}'.format(math.pi, math.tau))
# In[11]:
# 數字欄位的名字可以不用照順序
print('Math constants: π = {2}, e = {0}, τ = {1}'.format(math.e, math.tau, math.pi))
# In[12]:
# 如果全部欄位都按照順序,一個蘿蔔一個坑,那欄位裡的數字可以省略
'Math constants: π = {}, e = {}, τ = {}'.format(math.pi, math.e, math.tau)
# In[13]:
# 用文字指定欄位名字,而因為format()裡也明確指定參數的名字,所以參數列出來的順序就不重要了
print('Math constants: π = {Pi}, e = {e}, τ = {Tau}'.format(e=math.e, Pi=math.pi, Tau=math.tau))
# In[14]:
# 欄位可以重複指定使用
print('Math constants: π = {Pi}, τ = {Tau}, τ 其實就是 2π = 2 * {Pi}'.format(Pi=math.pi, Tau=math.tau))
# In[15]:
m = [math.pi, math.e, math.tau]
# list 卸載會塞到對應順序的欄位
print('Math constants: {}, {}, {}'.format(*m))
# In[16]:
n = {'pi': math.pi, 'e': math.e, 'tau': math.tau}
# dict 卸載會塞value到對應key的欄位
print('Math constants: π = {pi}, τ = {tau}, e = {e}'.format(**n))
# 或是只卸載 key
print('Math constants: {}, {}, {}'.format(*n))
# ### § `format` 指定寬度、對齊與空白填補
# In[17]:
# 靠左,空白處補 '-'
print('{:-<30}'.format('left aligned'))
# In[18]:
# 靠右
print('{:>30}'.format('right aligned'))
# In[19]:
# 置中,空白處補 '*'
print('{:*^30}'.format('centered'))
# ### § `format` 指定數值格式與小數精度
# In[20]:
# 沒有進制前綴符號
print('int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}'.format(42))
# In[21]:
# 加上進制前綴符號
print('int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}'.format(42))
# In[22]:
# 改變小數精度
print('constant π = {0:<030.2f}'.format(math.pi))
# In[23]:
# 改變數值顯示格式
print('constant π = {0:>030.2e}'.format(math.pi))
# In[24]:
# 用百分比顯示
print('π% = {:.3%}'.format(math.pi))