StringCut слева или справа от определенной позиции с помощью Mathematica - PullRequest
9 голосов
/ 31 мая 2011

Читая этот вопрос , я подумал, что следующая проблема будет проста с использованием StringSplit

Учитывая следующую строку, я хочу «вырезать» ее слева от каждого »D "такое, что:

  1. Я получаю Список фрагментов (с неизменной последовательностью)

  2. StringJoin @фрагменты возвращают исходную строку (но это не имеет значения, если мне нужно изменить порядок фрагментов, чтобы получить это).То есть последовательность внутри каждого фрагмента важна, и я не хочу терять никаких символов.

(Пример, который меня интересует, - это последовательность белка (строка), где каждый символ представляетаминокислота в однобуквенном коде. Я хочу получить теоретический список ВСЕХ фрагментов, полученных обработкой ферментом, который, как известно, расщепляется до «D»)

str = "MTPDKPSQYDKIEAELQDICNDVLELLDSKGDYFRYLSEVASGDN"

Лучшее, что я могу придумать, этовставьте пробел перед каждым «D», используя StringReplace, а затем используйте 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.

Обновление

Я добавил тег биоинформатики, и я подумал, что было бы интересно добавить пример из этого поля.

Следующее импортирует последовательность белка (бычий сывороточный альбумин, инвентарный номер 3336842) из ​​базы данных NCBI с использованием eutils , а затем генерирует (теоретический) трипсин Дайджест.Я предположил, что фермент трипсин расщепляется между остатками А1-А2, когда А1 представляет собой "R" или "K", при условии, что А2 не является "R", "K" или "P".Если у кого-то есть предложения по улучшению, пожалуйста, не стесняйтесь предлагать изменения.

Используя модификацию метода Сакры (возможно, необходимо удалить возврат каретки после '? 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 ]

7 голосов
/ 31 мая 2011

Я не могу построить ничего намного проще, чем ваш код. Вот код регулярного выражения, который вам может понравиться:

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

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

Используется шаблон негативного взгляда, заимствованный из этого сайта .


РЕДАКТИРОВАТЬ Добавление WReach крутое решение:
In[2]:= StringSplit[str, RegularExpression["(?<!P)(?=D)"]]

Out[2]= {"MTPDKPSQY", "DKIEAELQ", "DICN", "DVLELL", "DSKG", \
"DYFRYLSEVASG", "DN"}
3 голосов
/ 31 мая 2011

Вот несколько альтернативных решений:

Расщепление по любому вхождению "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"}
3 голосов
/ 31 мая 2011

Ваше первое решение не так уж и плохо, не так ли?Все, что я могу придумать, длиннее или страшнее этого.Проблема в том, что в исходной строке могут быть пробелы?

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

или

Prepend["D" <> # & /@ Rest[StringSplit[str, "D"]], First[StringSplit[str, "D"]]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...