--- title: List Comprehension tags: sprouts slideOptions: theme: solarized transition: 'fade' --- ## List Comprehension! Be pythonic --- # Pythonic? ---- # Very python ---- ## Why? - 簡潔 - 可讀 - 入境隨俗 ---- ## Example 翻轉一個list ---- ## C style ```python= A = [1,2,3,4,5] B = [] for i in range(len(A)-1, 0 ,-1): B.append(A[i]) ``` ---- ## Python style ```python= A = [1,2,3,4,5] B = A[::-1] ``` ---- ## Advance 將一到一百所有的偶數輸出 ---- ## C style ```python= for i in range(1,101): if i % 2 == 0: print(i) ``` ---- ## Python style ```python= # 利用list的語法特性 print(list(range(1,101))[1::2]) ``` --- ## List comprehension? ---- ## imagine a scenario ---- ## Question 輸出0~100之間,所有被2整除但不被5整除的數。 ---- ## Intuitive way ```python= for i in range(101): if i % 2 == 0 and i % 5 != 0: print(i) ``` ---- ## Pythonic way ```python= print([i for i in range(101) if i % 2 == 0 and i % 5 != 0]) ``` --- ## 正直善良的寫法 ```python= for i in range(101): if i % 2 == 0 and i % 5 != 0: print(i) ``` ## 黑魔法 ```python= print([i for i in range(101) if i % 2 == 0 and i % 5 != 0]) ``` ---- ## Definition ![](https://i.imgur.com/wiiEiFc.png) ---- ## List Comprehension 從入門到放棄,四步驟 ---- ## 心法 - 有list有\[\] - 想要的在前面 - 修飾的在後面 - 源頭在中間 ---- ## 黑魔法解析 ```python= [i for i in range(101) if i % 2 == 0 and i % 5 != 0] ``` - 有list有\[\] - i 是我想要的 - `if i % 2 == 0 and i % 5 != 0` 是修飾用的 - `for i in range(101)` 是源頭 ---- ### 當成篩子 ![](https://i.imgur.com/MueqI2S.png =300x400) --- ## 黑魔法練習s - 1 : 1-50所有的數 - 2 : 1-50所有5的倍數 - 3 : 1-100所有3的倍數但不是9的倍數 - 4 : 1-100所有2的次方數 ---- ## 黑魔法練習-1 - 1-50所有的數 ```python= [i for i in range(1,51)] ``` ---- ## 黑魔法練習-2 - 1-50所有5的倍數 ```python= [i for i in range(1,51) if i % 5 == 0] ``` ---- ## 黑魔法練習-3 - 1-100所有3的倍數但不是9的倍數 ```python= [i for i in range(1,101) if i % 3 == 0 and i % 9 != 0] ``` ---- ## 黑魔法練習-4 - 1-100所有2的次方數 ```python= [2**i for i in range(10) if 2**i < 101 and 2**i > 0] ``` --- ## 實用黑魔法 ---- ### 輸入處理-DNA雜訊處理 DNA有四種含氮鹼基,分別為ATGC,但在實際上,資料往往會出現在雜訊,因此必須過濾掉不可能出現的鹼基 - Input : ATCGATGCHATGCATFC ---- ## Intuitive Style ```python= k = input() new_k = "" for i in k: if i in "ATGC": new_k+=i ``` ---- ## 黑魔法Style ```python= "".join([i for i in input() if i in "ATGC"]) ``` - for i in input() - 以i遍歷input()回傳字串的每個字元 - if i in "ATGC" - 只有在"ATGC"裡的i才會通過 - i - Return i --- ## 進階黑魔法 如果要把錯誤用x取代呢? ---- ## Intuitie Style ```python= k = input() new_k = "" for i in k: if i in "ATGC": new_k+=i ``` ---- ## 黑魔法Style else 怎麼辦??? ---- ## Conditional Expression - `a if [condition] else b` - 以下簡稱CE ---- ## Example ```python= x = 3 k = x if x % 2 == 0 else x + 1 # 若x是2的倍數回傳x否則回傳x+1 print(k) # 4 ``` ---- ## if else 可以巢狀 ```python= if a == b: if b == c: # do something ``` ---- ## CE也可這樣 ```python= x = 9 "A" if x % 2 == 0 else \ "B" if x % 3 == 0 else "C" ``` ---- ## Ans: "B" ---- ## 精闢解說 - `"B" if x % 2 == 0 else ("B" if x % 3 == 0 else "C")` - 回傳`("B" if x % 3 == 0 else "C")` - `("B" if x % 3 == 0 else "C")` - 回傳`"B"` ---- # 回歸正題 ---- ## Original ```python= #[回傳值 迭代 遮罩] [i for i in input() if i in "ATGC"] ``` ## New ```python= #[Expression 迭代 遮罩] [i if i in "ATGC" else 'x' for i in input() ] ``` ---- ## [Expression 迭代 遮罩] --- ## 進階黑魔法練習-1 請輸出1-100之間2的倍數,若他也是3的倍數的話,請輸出原數字,否則請在數字前加上7122 ---- ## Solution ```python= [int("7122"+str(i)) if i % 3 != 0 else i for i in range(1,101) if i % 2 == 0] ``` - for i in range(101) - 迭代1~100之間的整數 - if i % 2 ==0 - 只讓2的倍數通過 - int("7122"+str(i)) if i % 3 != 0 else i - conditional expression ---- ## 進階黑魔法練習-2 ---- ## 改成一行版 ```python= my_list = [] for i in range(0,100): if i % 2 == 0: my_list.append(i) elif i % 7 == 0: my_list.append(-i) else: continue print(mylist) ``` ---- ## Solution ```python= [i if i % 2 == 0 else -i for i in range(0,100)\ if i % 2 == 0 or i % 7 == 0] ``` --- # 精益求精 ---- ## 脈絡 - for -> list comprehension - if else -> list comprehension ---- ## 巢狀迴圈 輸出9x9乘法表 ```python= for i in range(1,10): for j in range(1,10): print(i,j,i*j) ``` ---- ## 黑魔法 ```python= [(i,j,i*j) for i in range(1,10) for j in range(1,10))] ``` ---- ## 黑魔法細講 - Expression - `(i,j,i*j)` - Iter - for i in range(1,10) for j in range(1,10) - 一次 - i 跟 j 都要拿r ---- ## 這不一樣啊 ---- ## 小魔法 (only for py3) ```python= [print(i,j,i*j) for i in range(1,10) for j in range(1,10))] ``` ---- ## 小魔法解說 - 在python3,print是一個function,也就是說他屬於expression,而輸出是他的副作用,在python2,print是一個statement,因此無法丟到list comprehension內。 ---- ## 遮罩 x 巢狀 ---- ## 變形題 1 - 一樣是九九乘法表,但是對於每個數字只要輸出到n x q (q為偶數)。 ---- ## 老解法 ```python= for i in range(1,10): for j in range(1,10): if j % 2 == 0: print(i,j,i*j) ``` ---- ## list comprehension一解 ```python= [print(i,j,i*j) for i in range(1,10) for j in range(2,10,2)] ``` 但是我不要這個 ---- ## Try One xxx要是啥呢 ```python= [print(i,j,i*j) for i in range(1,10) for j in range(1,10) xxx] ``` ---- ## Ans ```python= [print(i,j,i*j) for i in range(1,10) \ for j in range(1,10) if j % 2 == 0] ``` ---- ## 變形題 2 - 一樣是九九乘法表,但是對於每個數字只要輸出到n x q (n小於5)。 ---- ## 老解法 ```python= for i in range(1,10): if i < 5 == 0: for j in range(1,10): print(i,j,i*j) ``` ---- ## list comprehension一解 ```python= [print(i,j,i*j) for i in range(1,5) for j in range(1,10)] ``` 但是我不要這個 ---- ## Try One xxx 或 yyy 要是啥呢 ```python= [print(i,j,i*j) for i in range(1,10) xxx for j in range(1,10) yyy] ``` ---- ## Ans ```python= [print(i,j,i*j) for i in range(1,10) \ if i < 5 for j in range(1,10)] ``` --- ## 還沒完喔XD ---- ## 剛剛的引言 - 巢狀for轉換 ---- ## 巢狀 ? - list comprehension可以巢狀嗎? ---- ## Yape - 因為list是個物件r ---- ## 題目 - 請用list儲存一個 5 x 5 Identity矩陣 ---- ## I 矩陣 ```python= 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 ``` ---- ## 簡單? - 這可是某知名外企面試題r ---- ## 老解法 ```python= identity = [] for i in range(5): row = [] for j in range(5): row.append(1 if i == j else 0) identity.append(row) ``` ---- ## 黑魔法 ```python= [[1 if i == j else 0 for i in range(5)] for j in range(5)] ``` --- ## 觸類旁通 - list : 『我有comprehension,很猛!!!』 - dict : 『你有,我也有 ! ! !』 ---- ## Dict Comprehension - 把 `[]` 換成 `{}` - 從單值便成key value配對 ---- ## Example ```python= {i: "hi"*i for i in range(5)} ``` ---- ## 衝突 - 如果有一個key對應到很多個value呢? ```python= {0: "hi"*i for i in range(5)} ``` - last one survive ---- ## 回憶過去 下列何者會有error呢? `[{ i : i for i in range(5)} for j in range(5)]` `{[i for i in range(5)] : "hi" for q in range(5)}` ---- ## 觸類旁通(誤) - tuple : 『把`[]`改成`()`是不是我也可以了?』 - 謎之聲 : 『拍謝,那是我~』 --- ## Final Challenge ---- ## Problem Given two string a, b, --- # Summary ---- ## Pros 1. 潮 2. 快 3. 看起來很像大神<(_ _)> ---- ## Cons 1. 可讀性低落 2. 腦袋很累 ---- ## Things Not Mentioned - Generator comprehension - Set comprehension --- ## Homework - 一行解掉judge上5題 - 不限題目 - Report - Code - 解說 - Mailto : b04611015@csie.ntu.edu.tw - Title : 資芽作業 『list comprehension』 --- # Q&A