2011-05-31 34 views
9

規定的位置向左或向右讀this question,我認爲以下問題將使用StringSplit「StringCut」來使用Mathematica

簡單考慮下面的字符串,我要來「切割」它向左每一個 「d」,使得:

  1. 我得到碎片的列表(帶序列不變)

  2. StringJoin @fragments給巴ck原始字符串(但如果我必須重新排序片段以獲取此內容則無關緊要)。也就是說,每個片段內的序列都很重要,我不想丟失任何字符。

(我對的例子是蛋白序列(串),其中每個字符表示在單字母代碼的氨基酸。我想獲得通過用酶處理所獲得的所有片段的理論列表已知的「d」)

str = "MTPDKPSQYDKIEAELQDICNDVLELLDSKGDYFRYLSEVASGDN" 

我可以想出是之前每個「d」,以插入一個空格使用StringReplace,然後使用StringSplit最好之前分裂。至少可以這麼說,這似乎相當尷尬。

frags1 = [email protected][str, "D" -> " D"] 

給作爲輸出:

{"MTP", "DKPSQY", "DKIEAELQ", "DICN", "DVLELL", "DSKG", "DYFRYLSEVASG", "DN"} 

,或者可選地,使用StringReplacePart

frags1alt = 
[email protected][str, " D", StringPosition[str, "D"]] 

最後(更實際地),如果我想 「d」 之前,分裂條件是前面的殘基不是「P」[即PD,(Pro-Asp)鍵未被切割],我這樣做如下:

[email protected][str, (x_ /; x != "P") ~~ "D" -> x ~~ " D"] 

有沒有更優雅的方式?

速度不一定是問題。我不太可能處理的字符串大於500個字符。我使用的MMA的7

更新

我已經添加了生物信息學的標籤,我認爲它可能有興趣從字段添加一個例子。

以下使用eutilsNCBI database輸入蛋白質序列(牛血清白蛋白,登錄號3336842),然後生成(理論)trypsin消化物。假設A2不是「R」,「K」或「P」,我認爲當A 1是「R」或「K」時,anticin酶在殘基A1-A2之間裂解。如果有人有任何改進建議,請隨時提出修改建議。

使用sakra方法的修改(回車後'?分貝=」可能需要被移除):

StringJoin /@ 
    Split[Characters[#], 
    And @@ Function[x, #1 != x] /@ {"R", "K"} || 
     Or @@ Function[xx, #2 == xx] /@ {"R", "K", "P"} &] & @ 
[email protected] 
    [email protected][ 
    "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=\ 
protein&id=3336842&rettype=fasta&retmode=text", "Data"] 

我可能笨拙在使用正則表達式的方法(薩沙/ WReach)做同樣的事情嘗試:

StringSplit[#, RegularExpression["(?![PKR])(?<=[KR])"]] &@ 
[email protected]@Import[...] 

輸出

{MK,WVTFISLLLLFSSAYSR,GVFRR,<<69>>,CCAADDK,EACFAVEGPK,LVVSTQTALA} 
+0

@ Mr.Wizard。感謝那些不錯的編輯。 – tomd 2011-06-03 14:45:15

回答

3

這裏有一些替代解決方案:

分裂由 「d」 中的任何發生:

In[18]:= StringJoin /@ Split[Characters["MTPDKPSQYDKIEAELQDICNDVLELLDSKGDYFRYLSEVASGDN"], #2!="D" &] 
Out[18]:= {"MTP", "DKPSQY", "DKIEAELQ", "DICN", "DVLELL", "DSKG", "DYFRYLSEVASG", "DN"} 

分裂由提供 「d」 中的任何發生它不是前面的「P」:

In[19]:= StringJoin /@ Split[Characters["MTPDKPSQYDKIEAELQDICNDVLELLDSKGDYFRYLSEVASGDN"], #2!="D" || #1=="P" &] 
Out[19]:= {"MTPDKPSQY", "DKIEAELQ", "DICN", "DVLELL", "DSKG", "DYFRYLSEVASG", "DN"} 
+1

我也對這些類型的操作使用了相同類型的'Split'構造。 @TomD沒有必要將字符保留在一個字符串中,而是使用字符列表來處理它們通常是有利的。 – Szabolcs 2011-06-02 09:16:09

+0

謝謝,我喜歡這個。正則表達式解決方案也非常整潔。 – tomd 2011-06-03 13:11:32

+0

@Szabolcs是的,那是學習的教訓之一! – tomd 2011-06-03 13:12:26

7

我不能構建任何簡單的代碼。這是一個正則表達式的代碼,你可能碰巧喜歡:

In[281]:= [email protected] 
StringReplace[str, RegularExpression["(?<!P)D"] -> " D"] 

Out[281]= {"MTPDKPSQY", "DKIEAELQ", "DICN", "DVLELL", "DSKG", \ 
"DYFRYLSEVASG", "DN"} 

它採用負回顧後發模式,從this site借來的。


編輯添加 WReach很酷的解決方案:

In[2]:= StringSplit[str, RegularExpression["(?<!P)(?=D)"]] 

Out[2]= {"MTPDKPSQY", "DKIEAELQ", "DICN", "DVLELL", "DSKG", \ 
"DYFRYLSEVASG", "DN"} 
+6

+1您可以將其簡化爲'StringSplit [str,RegularExpression [「(?<!P)(?= D)」]]'。 – WReach 2011-05-31 14:03:58

+1

+1,我瞭解了一些我不知道的有關正則表達式的東西,儘管這並不多。爲了確保我理解它,更新後的解決方案通過正向預測匹配「D」時使用負面後視,正向預測允許下一個字符串以「D」開始。一個簡單的例子就是用'「(?<!P)D」'試試這個,並進行比較。 – rcollyer 2011-06-01 03:23:12

+0

@rcollyer你的分析是正確的。 'StringSplit'通常排除它找到的所有分隔符。在這種情況下,分隔符是空字符串 - 空字符串,前面沒有* P *但後面跟着* D *。 – WReach 2011-06-02 03:01:55

3

你的第一個解決方案並不壞,是嗎?我所能想到的一切都比這更長或更醜。問題可能是原始字符串中有空格嗎?

StringCases[str, "D" | StartOfString ~~ Longest[Except["D"] ..]] 

Prepend["D" <> # & /@ Rest[StringSplit[str, "D"]], First[StringSplit[str, "D"]]] 
+0

謝謝。這些也是很好的解決方案。正如我上面所說的,我從這些答案中學到了很多東西,並且我不得不花費一點時間去解決它們。 (三個優秀的答案,IMO) – tomd 2011-06-03 13:16:52