'StringCut'使用Mathematica在定义位置的左侧或右侧

时间:2011-05-31 13:02:28

标签: string wolfram-mathematica bioinformatics

在阅读this question时,我认为使用StringSplit

会使以下问题变得简单

鉴于以下字符串,我想在每个“D”的左边“剪切”它,以便:

  1. 我得到列表的片段(序列未更改)

  2. StringJoin @ fragment返回原始字符串(但如果我必须重新排序片段以获得此字符串,则无关紧要)。也就是说,每个片段中的序列很重要,我不想丢失任何字符。

  3. (我感兴趣的例子是蛋白质序列(字符串),其中每个字符代表一个字母代码中的氨基酸。我想获得通过用已知分裂的酶处理获得的所有片段的理论列表“d”)

    str = "MTPDKPSQYDKIEAELQDICNDVLELLDSKGDYFRYLSEVASGDN"
    

    我能想到的最好的方法是使用StringReplace在每个“D”之前插入一个空格,然后使用StringSplit。至少可以说,这似乎很尴尬。

    frags1 = StringSplit@StringReplace[str, "D" -> " D"]
    

    作为输出:

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

    或者使用StringReplacePart

    frags1alt = 
     StringSplit@StringReplacePart[str, " D", StringPosition[str, "D"]]
    

    最后(更现实地),如果我想在“D”之前分裂,前提是它前面的残留物不是“P”[即PD,(Pro-Asp)键未被切割],我这样做如下:

    StringSplit@StringReplace[str, (x_ /; x != "P") ~~ "D" -> x ~~ " D"]
    

    有更优雅的方式吗?

    速度不一定是个问题。我不太可能处理大于500个字符的字符串。我正在使用Mma 7。

    更新

    我添加了生物信息学标签,我认为从该领域添加一个例子可能会引起兴趣。

    以下使用NCBI databaseeutils导入蛋白质序列(牛血清白蛋白,登录号3336842),然后生成(理论上的)trypsin消化物。假设A2不是“R”,“K”或“P”,我认为当A1是“R”或“K”时,酶tripin在残基A1-A2之间切割。如果有人有任何改进建议,请随时提出修改建议。

    使用sakra方法的修改('db ='之后的回车可能需要删除):

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

    我可能尝试使用正则表达式方法(Sasha / WReach)做同样的事情:

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

    输出

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

3 个答案:

答案 0 :(得分:7)

我无法构建任何比你的代码更简单的东西。这是一个正则表达式代码,您可能会喜欢它:

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

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

它使用负面的lookbehind模式,借鉴this site


编辑添加WReach很酷的解决方案:

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

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

答案 1 :(得分:3)

你的第一个解决方案并不是那么糟糕,是吗?我能想到的一切都比这更长或更丑。问题是原始字符串中可能有空格吗?

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

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

答案 2 :(得分: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"}