我目前正在使用 SELFIES(自參考嵌入字串,github:https ://github.com/aspuru-guzik-group/selfies ),它基本上是分子的字串表示。基本上它是由括號定義的標記序列,例如丙烷將被寫為“[C][C][C]”。我想找到獲取令牌串列的最有效方法,如下所示:
selfies= "[C][C][C]"
tokens= some_function(selfies)
tokens
["[C]","[C]","[C]"]
我已經找到了 3 種方法來做到這一點:
- 使用來自 github 的“本機”功能(https://github.com/aspuru-guzik-group/selfies/blob/master/selfies/utils/selfies_utils.py):
def split_selfies(selfies: str) -> Iterator[str]:
"""Tokenizes a SELFIES string into its individual symbols.
:param selfies: a SELFIES string.
:return: the symbols of the SELFIES string one-by-one with order preserved.
:Example:
>>> import selfies as sf
>>> list(sf.split_selfies("[C][=C][F].[C]"))
['[C]', '[=C]', '[F]', '.', '[C]']
"""
left_idx = selfies.find("[")
while 0 <= left_idx < len(selfies):
right_idx = selfies.find("]", left_idx 1)
if right_idx == -1:
raise ValueError("malformed SELFIES string, hanging '[' bracket")
next_symbol = selfies[left_idx: right_idx 1]
yield next_symbol
left_idx = right_idx 1
if selfies[left_idx: left_idx 1] == ".":
yield "."
left_idx = 1
%%timeit
tokens= list(sf.split_selfies(selfies))
3.41 μs ± 22.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
編輯: ”。” 在我的情況下從未出現過,并且為了速度而在解決方案 2 和 3 中不考慮它
這有點慢,可能是因為轉換為串列
- 來自圖書館的創建者(https://github.com/aspuru-guzik-group/stoned-selfies/blob/main/GA_rediscover.py):
def get_selfie_chars(selfies):
'''Obtain a list of all selfie characters in string selfie
Parameters:
selfie (string) : A selfie string - representing a molecule
Example:
>>> get_selfie_chars('[C][=C][C][=C][C][=C][Ring1][Branch1_1]')
['[C]', '[=C]', '[C]', '[=C]', '[C]', '[=C]', '[Ring1]', '[Branch1_1]']
Returns:
chars_selfie: list of selfie characters present in molecule selfie
'''
chars_selfie = [] # A list of all SELFIE sybols from string selfie
while selfie != '':
chars_selfie.append(selfie[selfie.find('['): selfie.find(']') 1])
selfie = selfie[selfie.find(']') 1:]
return chars_selfie
%%timeit
tokens= get_selfie_chars(selfies)
3.44 μs ± 43.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
令人驚訝的是,它所花費的時間與本機函式大致相同
- 我的實作結合了串列理解、切片和 .split()
def selfies_split(selfies):
return [block "]" for block in selfies.split("]")][:-1]
%%timeit
tokens=selfies_split(selfies)
1.05 μs ± 53.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
我的實作快了大約 3 倍,但我認為最有效的標記化方法可能是使用帶有 re 包的正則運算式,但我從未使用過它,而且我對正則運算式并不特別滿意。所以我看不到如何以產生最佳結果的方式實施它。
編輯:
- 從答案建議:
def stackoverflow_1_split(selfies):
atoms = selfies[1:-1].replace('][', "$").split("$")
return list(map('[{}]'.format, atoms))
%%timeit
tokens=stackoverflow_1_split(selfies)
1.75 μs ± 101 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
如果沒有串列轉換,它實際上比我的實作更快(575 ns /- 10 ns),但串列是必需的
- 答案的第二個建議:
import re
def stackoverflow_2_split(selfies):
return re.findall(r".*?]", selfies)
%%timeit
tokens=stackoverflow_2_split(selfies)
1.81 μs ± 110 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
令人驚訝的是,re 似乎并沒有優于其他解決方案
- 答案的第三個建議:
def stackoverflow_3_split(selfies):
return selfies.replace(']', '] ').split()
%%timeit
tokens=stackoverflow_3_split(selfies)
485 ns ± 4.04 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
這是迄今為止最快的解決方案,比我的實作快大約 2 倍,干得好,凱利!
uj5u.com熱心網友回復:
其他:
selfies.replace(']', '] ').split()
使用 50 個代幣進行基準測驗(因為您說這是您的意思):
7.29 us original
3.91 us Kelly <= mine
8.06 us keepAlive
8.87 us trincot
用你的"[C][C][C]"代替:
0.87 us original
0.44 us Kelly
0.88 us keepAlive
1.45 us trincot
代碼(在線試用!):
from timeit import repeat
import re
def original(selfies):
return [block "]" for block in selfies.split("]")][:-1]
def Kelly(selfies):
return selfies.replace(']', '] ').split()
def keepAlive(selfies):
atoms = selfies[1:-1].split('][')
return [f'[{a}]' for a in atoms]
def trincot(selfie):
return re.findall(r".*?]", selfie)
fs = original, Kelly, keepAlive, trincot
selfies = ''.join(f'[{i}]' for i in range(50))
expect = original(selfies)
for f in fs:
print(f(selfies) == expect, f.__name__)
for _ in range(3):
print()
for f in fs:
number = 1000
t = min(repeat(lambda: f(selfies), number=number)) / number
print('%.2f us ' % (t * 1e6), f.__name__)
uj5u.com熱心網友回復:
使用正則運算式,您可以執行以下操作:
import re
def get_selfie_chars(selfie):
return re.findall(r".*?]", selfie)
如果一個點應該是一個單獨的匹配,那么:
return re.findall(r"\.|.*?]", selfie)
uj5u.com熱心網友回復:
怎么辦
>>> atoms = selfies[1:-1].split('][')
>>> atoms
["C","C","C"]
假設您不再需要方括號。否則,你最終可以做
>>> [f'[{a}]' for a in atoms]
["[C]","[C]","[C]"]
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/525919.html
上一篇:正則運算式匹配單個“:”欄位分隔符之間的字串并排除它們,當字串還包含“::”欄位分隔符時
下一篇:正則運算式在特定行中添加擴展名
