006. HAMM(Counting Point Mutations)+asterisk星號用法+zip()語法

更新於 發佈於 閱讀時間約 19 分鐘

題目連結


今天文章比較長,要冷靜忍耐一下

(文末有提到zip()asterisk星號用法,篇幅hen長)


輸入兩基因序列,比對這兩序列中有幾個不一樣的地方。

計算兩字串不同字符的個數,這個就稱為漢明距離 (Hamming distance)


11110000
01110001

上述範例經過逐位比較後,得到漢明距離為2

代表需要兩個步驟(單一位元的替換)才能讓兩字串相同



漢明距離 與 漢明碼 有關聯
漢明碼(Hamming Code)是最早的一種 系統糾錯碼/錯誤更正碼(ECC, error-correcting code)
引入”檢查位元(Parity bits)“,可以發現並修正一個錯誤,常用在封包傳輸



輸入

GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT


輸出

7



程式碼

data = \
"""
GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
"""

lines = data.splitlines()
lines = [line.strip() for line in lines if line.strip()]

count = 0
for i in range(len(lines[0])):
if lines[0][i] != lines[-1][i]:
count += 1

print(count)


函式寫法

def hamming_distance(s: str, t: str) -> int:
total = 0
zipped = zip(s, t)
for a, b in zipped:
if a != b:
total += 1

return total
# return sum(1 for a, b in zip(s, t) if a != b) # 單行精簡寫法

# 手動拆分兩序列
source = "GAGCCTACTAACGGGAT"
target = "CATCGTAATGACGGCCT"
print(hamming_distance(source, target))



迴圈陷阱

在過濾資料(剔除空字串、空物件)時,

不建議在迭代陣列(集合)的同時,對陣列本身進行新增/刪除

因為這會改變原先長度和索引順序,出現意料之外的結果

ex: 刪除陣列中的元素時,陣列會「變短」,然而for迴圈的索引卻「照原本的長度走」

錯誤用法

# 錯誤寫法 例1:看似正常的情況
items = ["a", "", "b", "", "c"]
for item in items:
if not item:
items.remove(item) # 不要這樣做!別在迴圈中修改列表,會造成執行順序錯亂(跳過元素)
print("錯誤寫法 例1:", items) # ["a", "b", "c"]


# 錯誤寫法 例2:出現非預期的結果
items = ["a", "", "b", "", "", "c"]
for item in items:
if not item:
items.remove(item)
print("錯誤寫法 例2:", items) # ["a", "b", "", "c"]


正確的寫法

使用新的陣列來儲存所需要的資料

# 正確寫法(迴圈版):
items = ["a", "", "b", "", "", "c"]
new_items = []
for item in items:
if item: # 只留下真值(篩掉所有falsy值 ex:"", 0, None, False)
new_items.append(item)
print("正確寫法(迴圈版):", new_items) # ['a', 'b', 'c']


# 正確寫法(精簡版):
items = ["a", "", "b", "", "", "c"]
items = [
item
for item in items
if item
]
# items = [item for item in items if item] # 單行寫法(List Comprehension)
print("正確寫法(精簡版):", items) # ['a', 'b', 'c']


另外,

if itemif not item是判斷 truthy/falsy value:
空字串""、整數0、浮點數0.0、布林值False、空值None、空容器[]{}()

if (item != "")則只有過濾空字串""






Python zip()用法

zip具有拉鍊、打包、壓縮的意思,可將多個元素配對,打包成一個元組



打包範例(可打包多個元素)

# ==== 範例1 ====
zipped = zip([1, 2, 3], ['a', 'b', 'c'])
print("範例1:", zipped) # <zip object at 0x12bc43a00> 直接輸出是物件位址
print("範例1:", list(zipped)) # [(1, 'a'), (2, 'b'), (3, 'c')]
print("範例1:", list(zipped)) # [] => 空了

# ==== 範例2 ====
student = ['小明', '小華', '小美', '小夫']
score = [85, 92, 78, 88]
subject = ['數學', '數學', '數學', '數學']

class_gradebook = zip(student, score, subject)
# [('小明', 85, '數學'), ('小美', 92, '數學'), ('阿強', 78, '數學'), ('阿珍', 88, '數學')]

for student, score, subject in class_gradebook:
print("範例2:", student, score, subject)

# 小明 85 數學
# 小美 92 數學
# 阿強 78 數學
# 阿珍 88 數學


zip()陷阱

但是在運用zip()時,也要小心使用陷阱

# ==== 陷阱1 ====
zipped = zip([1, 2, 3], ['a', 'b', 'c'])
print("陷阱1:", zipped) # <zip object at 0x12bc43a00> 直接輸出是物件位址
print("陷阱1:", list(zipped)) # [(1, 'a'), (2, 'b'), (3, 'c')]
print("陷阱1:", list(zipped)) # [] => 空了

# ==== 陷阱2 ====
zipped = zip([1, 2, 3], ['a', 'b', 'c'])
list(zipped)
print("陷阱2:", list(zipped)) # [] => 直接空了

z = list(zipped) # 要用變數將zip迭代結果存起來,才有辦法重複使用

# ==== 陷阱3 ====
# 長度不一致時,zip 會自動對齊最短長度
# 超出部分會被忽略,而不會報錯
zipped = zip([1, 2, 3], ['a', 'b', 'c', 'd']) # 因長度不匹配,'d'會被丟掉
print("陷阱3:", list(zipped)) # [(1, 'a'), (2, 'b'), (3, 'c')]

zip()是一種懶惰迭代器(Lazy Iterator),是只能走過一遍的迭代器(一次性消耗品)

裡面的東西(資料流)只能倒出來一次,用一次就沒了,再用就是空的。除非額外使用變數將「倒出結果」儲存起來。

相同類型的iterator還有:map(), filter(), enumerate(), open(), iter()



拆解方式unzip

因為zipped過後,內容已經被分為「欄列」可以視作一張「表(Table)」了

raw-image

所以拆解zip包的方式,自然分成兩種:橫向拆分 vs 直的解開

  1. 拆包:多變數賦值/序列解包(unpacking)
    把「一包多個值」分配給多個變數 => 拿n個變數去「接n個tuple」。
  2. 解包:轉置解包/參數解包(*unpacking)
    把包裝資料攤平、展開 => 把包還原為「打包前」的樣子

兩種方式「變數的數量」都要正確

names = ['早餐', '午餐', '晚餐']
costs = ['$35', '$80', '$65']

zipped = list(zip(names, costs)) # 由3個tuple組成的list
print("記錄:", zipped) # [('早餐', '$35'), ('午餐', '$80'), ('晚餐', '$65')]

# 拆解方式1:拆包 多變數賦值/序列解包
record_1, record_2, record_3 = zipped
print(record_1, record_2, record_3) # ('早餐', '$35') ('午餐', '$80') ('晚餐', '$65')

# 拆解方式2:解包 轉置解包/參數解包
names, costs = zip(*zipped)
print(names, costs) # ('早餐', '午餐', '晚餐') ('$35', '$80', '$65')

print("項目:", names) # ('早餐', '午餐', '晚餐')
print("開銷:", costs) # ('$35', '$80', '$65')



---


Python 星號(*) asterisk

在Python中,偶爾會看到***的用法

簡單來說,這兩者代表的是 一個元組/陣列/字典裡面的剩餘元素


單星號*(asterisk, single star):

打包/解包 可迭代物件 unpack iterable(list/tuple)

處理的是位置參數(positional arguments),按照位置順序解析


雙星號**(double asterisk, double star):

打包/解包 字典 unpack dictionary(key/value)

處理的是具名參數(keyword arguments),按照參數名稱解析


先來看解包的例子:

# ==== single star ====
args = (1, 2, 3, 4)
print(*args) # 解開成 1 2 3 4

list1 = [1, 2, 3]
list2 = [4, 5]
combined = [*list1, *list2] # 解開陣列,存入新陣列中
print(combined) # [1, 2, 3, 4, 5]

zipped = [('早餐', '$35'), ('午餐', '$80'), ('晚餐', '$65')]
record_1, *others = zipped # 把右邊拆開放到左邊
print(record_1) # ('早餐', '$35')
print(others) # [('午餐', '$80'), ('晚餐', '$65')]

# ==== double star ====
dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3}
merged = {**dict1, **dict2} # 解開字典,存入新字典中
print(merged) # {'a': 1, 'b': 2, 'c': 3}


再來看打包(收集、組裝)的例子:

# ==== single star ====
def add_all(*args): # 收參數(打包),把傳進來的位置參數放進tuple中
print(*args) # 1 2 3 4 => 解參數、解包後的樣子
print(args) # (1, 2, 3, 4) => 未解包的模樣
print(args[0]) # 1

return sum(args)

total = add_all(1, 2, 3, 4)
print(total) # 10

# ==== double star ====
def parse_data(**kwargs): # 允許無限制數量的關鍵字參數
for name, cost in kwargs.items():
print(name, cost)

record = {'早餐': '$35', '午餐': '$80'}

parse_data(**record)
# 早餐 $35
# 午餐 $80

parse_data(午餐='$50', 晚餐='$30', 宵夜='$250') # 支援跟鬼一樣的用法
# 午餐 $50
# 晚餐 $30
# 宵夜 $250


最後是

強制使用具名參數/位置參數

# 一般寫法
def record_item(item: str, cost: str):
print(item, cost)

record_item("早餐", "$10") # 位置參數,按照順序填
record_item(item="午餐", cost="$120") # 具名參數,指定關鍵字

# 強制使用具名參數 => 在*右側的參數,只能用具名參數(keyword)
def record_item_k1(*, item: str, cost: str):
print(item, cost)

# record_item_k1("早餐", "$10") => 會出錯,不能用"位置參數"
record_item_k1(item="午餐", cost="$120")

def record_item_k2(item: str, *, cost: str): # *在中間 => 只有*右側的cost需要使用具名參數
print(item, cost)

record_item_k2(item="午餐", cost="$120")
record_item_k2("晚餐", cost="$250") # 這行可運作

# 強制使用位置參數 => 在/左側的參數,只能用位置參數(positional)
def record_item_p1(item: str, cost: str, /):
print(item, cost)

# record_item_p1(item="午餐", cost="$120") # 會出錯,不能用"具名參數"
record_item_p1("晚餐", "$250") # 這行可運作




# 兩者混用mix(強制具名、強制位置)
# 若兩同時存在,/必須出現在*前面
def record_item_m1(item: str, /, cost: str, *, notes: str):
print(item, cost)

record_item_m1("蹦迪", "$1000", notes="好貴")

# def record_item_m2(item: str, *, cost: str, /): # 這行會報錯 SyntaxError: / must be ahead of *
# print(item, cost)


最終的大雜燴

打包/解包 搭配 強制使用具名參數/位置參數

# item, cost 只能用位置參數。剩下傳入的位置參數都會被*extra收集起成tuple
def record_1(item, cost, /, *extra):
print(item, cost, extra) # 早餐 $50 ('便利商店', '一杯咖啡、兩顆茶葉蛋')
print(*extra) # 早餐 $50 ('便利商店', '一杯咖啡、兩顆茶葉蛋')

record_1("早餐", "$50", "便利商店", "一杯咖啡、兩顆茶葉蛋")

# item, cost 只能用具名參數。剩下傳入的具名參數都會被**extra收集成dict
def record_2(*, item, cost, **extra):
print(item, cost, extra) # 晚餐 $120 {'地點': '火鍋店', '備註': '原味健康火鍋'}
print(*extra) # 地點 備註 => 印出key
# print(**extra) # 會報錯 => print()不支援印出具名參數

record_2(item="晚餐", cost="$120", 地點="火鍋店", 備註="原味健康火鍋")



留言
avatar-img
留言分享你的想法!
avatar-img
生物資訊實驗室
0會員
17內容數
這裡存放著滿滿的大平台!Rosalind 生物資訊解題平台的學習過程! 📢 適合對象: ✅ 想學習生物資訊的程式新手 ✅ 對Python程式有基礎,想挑戰 Rosalind 題目的解題者 ✅ 對DNA、蛋白質、基因組數據分析有興趣的人
生物資訊實驗室的其他內容
2025/04/16
題目連結 密碼子為三個鹼基一組的序列 就像把一段RNA序列拆包、逐個decode成對應的蛋白質字母 輸入 AUGGCCAUGGCGCCCAGAACUGAGAUCAAUAGUACCCGUAUUAACGGGUGA 輸出 MAMAPRTEINSTRING 首先就是要建立出密碼
Thumbnail
2025/04/16
題目連結 密碼子為三個鹼基一組的序列 就像把一段RNA序列拆包、逐個decode成對應的蛋白質字母 輸入 AUGGCCAUGGCGCCCAGAACUGAGAUCAAUAGUACCCGUAUUAACGGGUGA 輸出 MAMAPRTEINSTRING 首先就是要建立出密碼
Thumbnail
2025/04/12
題目連結 孟德爾第一定律(Mendel's First Law),是遺傳學中的分離律 題目輸入 2 2 2 輸出 0.78333 蛤??? 當三個2擺在一起 怎麼計算也不會是這個數字吧? 不可能,絕對不可能! 這麼醜的數字0.78333到底是怎麼湊來的? 幾
Thumbnail
2025/04/12
題目連結 孟德爾第一定律(Mendel's First Law),是遺傳學中的分離律 題目輸入 2 2 2 輸出 0.78333 蛤??? 當三個2擺在一起 怎麼計算也不會是這個數字吧? 不可能,絕對不可能! 這麼醜的數字0.78333到底是怎麼湊來的? 幾
Thumbnail
2025/04/04
題目連結 這題要我們讀入多個DNA序列(FASTA格式) 從中找出GC含量最高的那一段序列,並輸出GC含量(保留小數到第六位) 普遍稱呼「GC」而非「CG」,我也不知道為什麼 ╮(╯_╰)╭ 但讓我聯想到,GC在程式語言專指垃圾回收(Garbage Collection) 首先要
Thumbnail
2025/04/04
題目連結 這題要我們讀入多個DNA序列(FASTA格式) 從中找出GC含量最高的那一段序列,並輸出GC含量(保留小數到第六位) 普遍稱呼「GC」而非「CG」,我也不知道為什麼 ╮(╯_╰)╭ 但讓我聯想到,GC在程式語言專指垃圾回收(Garbage Collection) 首先要
Thumbnail
看更多
你可能也想看
Thumbnail
常常被朋友問「哪裡買的?」嗎?透過蝦皮分潤計畫,把日常購物的分享多加一個步驟,就能轉換成現金回饋。門檻低、申請簡單,特別適合學生與上班族,讓零碎時間也能創造小確幸。
Thumbnail
常常被朋友問「哪裡買的?」嗎?透過蝦皮分潤計畫,把日常購物的分享多加一個步驟,就能轉換成現金回饋。門檻低、申請簡單,特別適合學生與上班族,讓零碎時間也能創造小確幸。
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
題目連結 今天文章比較長,要冷靜忍耐一下 (文末有提到zip()與asterisk星號用法,篇幅hen長) 輸入兩基因序列,比對這兩序列中有幾個不一樣的地方。 計算兩字串不同字符的個數,這個就稱為漢明距離 (Hamming distance) 11110000 01110001
Thumbnail
題目連結 今天文章比較長,要冷靜忍耐一下 (文末有提到zip()與asterisk星號用法,篇幅hen長) 輸入兩基因序列,比對這兩序列中有幾個不一樣的地方。 計算兩字串不同字符的個數,這個就稱為漢明距離 (Hamming distance) 11110000 01110001
Thumbnail
題目敘述 Find K-th Smallest Pair Distance 給定一個輸入陣列nums和 參數k。 請找出第k小的pair distance是多少? pair distance定義為 abs( nums[i] - nums[j]), i 不等於j 也就是任意兩陣列元素差值的絕對值
Thumbnail
題目敘述 Find K-th Smallest Pair Distance 給定一個輸入陣列nums和 參數k。 請找出第k小的pair distance是多少? pair distance定義為 abs( nums[i] - nums[j]), i 不等於j 也就是任意兩陣列元素差值的絕對值
Thumbnail
題目敘述 Merge Nodes in Between Zeros 給定一個鏈結串列,合併非零區間的節點(以加總的方式合併),輸出合併後的鏈結串列。
Thumbnail
題目敘述 Merge Nodes in Between Zeros 給定一個鏈結串列,合併非零區間的節點(以加總的方式合併),輸出合併後的鏈結串列。
Thumbnail
看到題目問「種類」時,集合就是你最好的朋友。
Thumbnail
看到題目問「種類」時,集合就是你最好的朋友。
Thumbnail
給定一個字串陣列,請把它們所共有的字元伴隨著出現次數輸出。這篇文章介紹如何使用字典統計出現次數,和字典取交集的方法來解決此問題。並提供了複雜度分析和關鍵知識點。
Thumbnail
給定一個字串陣列,請把它們所共有的字元伴隨著出現次數輸出。這篇文章介紹如何使用字典統計出現次數,和字典取交集的方法來解決此問題。並提供了複雜度分析和關鍵知識點。
Thumbnail
給定一個字串s,以s擁有的字元製造迴文字串。要能製造出的迴文字串長度最長是多少,觀察迴文字串不外乎兩種模式對稱部分 + 核心字元 + 對稱部分,其中,核心字元在正中央出現一次,或者 對稱部分 + 對稱部分。使用演算法統計出現次數並推理出盡可能充分利用每個字元的迴文字串製造方法。
Thumbnail
給定一個字串s,以s擁有的字元製造迴文字串。要能製造出的迴文字串長度最長是多少,觀察迴文字串不外乎兩種模式對稱部分 + 核心字元 + 對稱部分,其中,核心字元在正中央出現一次,或者 對稱部分 + 對稱部分。使用演算法統計出現次數並推理出盡可能充分利用每個字元的迴文字串製造方法。
Thumbnail
Append Characters to String to Make Subsequence 給定兩個字串s和字串t。 請計算最少的字元串接數量是多少,串接在s的尾端,使得t是s的子序列。 測試範例 Example 1: Input: s = "coaching", t =
Thumbnail
Append Characters to String to Make Subsequence 給定兩個字串s和字串t。 請計算最少的字元串接數量是多少,串接在s的尾端,使得t是s的子序列。 測試範例 Example 1: Input: s = "coaching", t =
Thumbnail
輸入給定一個已經從小到大排序好,而且彼此互質的整數陣列, 請問任取兩數分別當作分子、分母,第k小的分數是多少? 輸出請以 [分子,分母] 的形式回傳答案。
Thumbnail
輸入給定一個已經從小到大排序好,而且彼此互質的整數陣列, 請問任取兩數分別當作分子、分母,第k小的分數是多少? 輸出請以 [分子,分母] 的形式回傳答案。
Thumbnail
題目敘述 題目會給定我們兩個輸入字串word1, word2,要求我們依照word1,word2,word1,word2, ... 交叉前進的方式,合併兩個字串,作為輸出。 題目的原文敘述 測試範例 Example 1: Input: word1 = "abc", word2 = "pq
Thumbnail
題目敘述 題目會給定我們兩個輸入字串word1, word2,要求我們依照word1,word2,word1,word2, ... 交叉前進的方式,合併兩個字串,作為輸出。 題目的原文敘述 測試範例 Example 1: Input: word1 = "abc", word2 = "pq
Thumbnail
題目敘述 給定兩個字串word1和word2,每次操作時,可以有三個選項 插入一個字元 刪除一個字元 替換一個字元 請問把word1轉換成word2的最小操作次數是多少? 題目的原文敘述 約束條件 Constraints: 0 <= word1.length, word2.le
Thumbnail
題目敘述 給定兩個字串word1和word2,每次操作時,可以有三個選項 插入一個字元 刪除一個字元 替換一個字元 請問把word1轉換成word2的最小操作次數是多少? 題目的原文敘述 約束條件 Constraints: 0 <= word1.length, word2.le
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News