Вставьте символ новой строки каждые 10 символов в строке, используя Julia
Я хочу вставить символ новой строки каждые 10 символов в последовательности белка:
seq="MSKNKSPLLNESEKMMSEMLPMKVSQSKLNYEEKVYIPTTIRNRKQHCFRRFFPYIALFQ"
В Perl это очень просто:
$seq=~s/(.{10})/$1\n/g ; # does the job!
perl -e '$seq="MSKNKSPLLNESEKMMSEMLPMKVSQSKLNYEEKVYIPTTIRNRKQHCFRRFFPYIALFQ"; $seq=~s/(.{10})/$1\n/g; print $seq'
MSKNKSPLLN
ESEKMMSEML
PMKVSQSKLN
YEEKVYIPTT
IRNRKQHCFR
RFFPYIALFQ
В Юлии
replace(seq, r"(.{10})" , "\n")
не работает, потому что я не знаю, как получить группу захвата (. {10}) и заменить ее на себя + "\n"
julia> replace(seq, r"(.{10})" , "\n")
"\n\n\n\n\n\n"
Чтобы сделать это, мне нужно выполнить 2 шага:
julia> a=matchall(r"(.{1,10})" ,seq)
6-element Array{SubString{UTF8String},1}:
"MSKNKSPLLN"
"ESEKMMSEML"
"PMKVSQSKLN"
"YEEKVYIPTT"
"IRNRKQHCFR"
"RFFPYIALFQ"
julia> b=join(a, "\n")
"MSKNKSPLLN\nESEKMMSEML\nPMKVSQSKLN\nYEEKVYIPTT\nIRNRKQHCFR\nRFFPYIALFQ"
julia> println(b)
MSKNKSPLLN
ESEKMMSEML
PMKVSQSKLN
YEEKVYIPTT
IRNRKQHCFR
RFFPYIALFQ
# Caution :
a=matchall(r"(.{10})" ,seq) # wrong if seq is not exactly a multiple of 10 !
julia> seq
"MSKNKSPLLNESEKMMSEMLPMKVSQSKLNYEEKVYIPTTIRNRKQHCFRRFFPYIAL"
julia> matchall(r"(.{10})" ,seq)
5-element Array{SubString{UTF8String},1}:
"MSKNKSPLLN"
"ESEKMMSEML"
"PMKVSQSKLN"
"YEEKVYIPTT"
"IRNRKQHCFR"
julia> matchall(r"(.{1,10})" ,seq)
6-element Array{SubString{UTF8String},1}:
"MSKNKSPLLN"
"ESEKMMSEML"
"PMKVSQSKLN"
"YEEKVYIPTT"
"IRNRKQHCFR"
"RFFPYIAL"
Есть ли одношаговое решение или лучший (более быстрый) способ?
Просто для удовольствия эталон со всеми этими интересными ответами! (обновлено с julia 5.0)
function loop(a)
last = 0
#create the interval, in your case 10
salt = 10
#iterate in string (starts in the 10th value, don't forget julia use 1 to first index)
for i in salt:salt+1:length(a)
# replace the string for a new one with '\n'
a = string(a[1:i], '\n', a[i+1:length(a)])
last = Int64(i)
end
# replace the rest
a = string(a[1:length(a) - last % salt + 1], '\n', a[length(a) - last % salt + 2:length(a)])
println(a)
end
function regex1(seq)
a=matchall(r"(.{1,10})" ,seq)
b=join(a, "\n")
println(b)
end
function regex2(seq)
a=join(split(replace(seq, r"(.{10})", s"\1 ")), "\n")
println(a)
end
function regex3(seq)
a=replace(seq, r"(.{10})", Base.SubstitutionString("\\1\n"))
a= chomp(a) # because there is a new line at the end
println(a)
end
function intrapad(seq::String)
buf = IOBuffer((length(seq)*11)>>3) # big enough buffer
for i=1:10:length(seq)
write(buf,SubString(seq,i,i+9),'\n')
end
#return
print(takebuf_string(buf))
end
function join_substring(seq)
a=join((SubString(seq,i,i+9) for i=1:10:length(seq)),'\n')
println(a)
end
seq="MSKNKSPLLNESEKMMSEMLPMKVSQSKLNYEEKVYIPTTIRNRKQHCFRRFFPYIALFQ"
for i = 1:5
println("loop :")
@time loop(seq)
println("regex1 :")
@time regex1(seq)
println("regex2 :")
@time regex2(seq)
println("regex3 :")
@time regex3(seq)
println("intrapad :")
@time intrapad(seq)
println("join substring :")
@time join_substring(seq)
end
Я изменил контрольный показатель, чтобы выполнить 5 раз @time, и я публикую здесь результаты после 5 выполнения @time:
loop :
MSKNKSPLLN
ESEKMMSEML
PMKVSQSKLN
YEEKVYIPTT
IRNRKQHCFR
RFFPYIA
LFQ
0.000013 seconds (53 allocations: 3.359 KB)
regex1 :
MSKNKSPLLN
ESEKMMSEML
PMKVSQSKLN
YEEKVYIPTT
IRNRKQHCFR
RFFPYIALFQ
0.000013 seconds (49 allocations: 1.344 KB)
regex2 :
MSKNKSPLLN
ESEKMMSEML
PMKVSQSKLN
YEEKVYIPTT
IRNRKQHCFR
RFFPYIALFQ
0.000017 seconds (47 allocations: 1.703 KB)
regex3 :
MSKNKSPLLN
ESEKMMSEML
PMKVSQSKLN
YEEKVYIPTT
IRNRKQHCFR
RFFPYIALFQ
0.000013 seconds (31 allocations: 976 bytes)
intrapad :
MSKNKSPLLN
ESEKMMSEML
PMKVSQSKLN
YEEKVYIPTT
IRNRKQHCFR
RFFPYIALFQ
0.000007 seconds (9 allocations: 608 bytes)
join substring :
MSKNKSPLLN
ESEKMMSEML
PMKVSQSKLN
YEEKVYIPTT
IRNRKQHCFR
RFFPYIALFQ
0.000012 seconds (21 allocations: 800 bytes)
Внутрипапка теперь первая;)
Ответы
Ответ 1
Как и @daycaster, вы можете использовать s"\1"
в качестве строки замены для поддержки групп захвата. Проблема в том, что специальный синтаксис строки s""
не поддерживает специальные символы, такие как \n
. Вы можете обойти это, вручную создав объект SubstitutionString
, но тогда вам нужно избежать \
в \1
:
julia> replace(seq, r"(.{10})", Base.SubstitutionString("\\1\n"))
"MSKNKSPLLN\nESEKMMSEML\nPMKVSQSKLN\nYEEKVYIPTT\nIRNRKQHCFR\nRFFPYIALFQ\n"
Ответ 2
Если скорость является проблемой, возможно, лучше избегать более тяжелых инструментов, таких как регулярные выражения, и попытаться просто выполнить работу на низком уровне, например:
function intrapad(seq::String)
buf = IOBuffer((length(seq)*11)>>3) # big enough buffer
for i=1:10:length(seq)
write(buf,SubString(seq,i,i+9),'\n')
end
return takebuf_string(buf)
end
Скорость исходит из минимизации распределения с использованием IOBuffer и SubStrings. Используя пакет BenchmarkTools, мы имеем:
julia> @benchmark intrapad(seq)
BenchmarkTools.Trial:
memory estimate: 624.00 bytes
allocs estimate: 10
minimum time: 729.00 ns (0.00% GC)
median time: 767.00 ns (0.00% GC)
mean time: 862.99 ns (7.84% GC)
maximum time: 26.86 μs (96.21% GC)
julia> @benchmark replace(seq, r"(.{10})", Base.SubstitutionString("\\1\n"))
BenchmarkTools.Trial:
memory estimate: 720.00 bytes
allocs estimate: 26
minimum time: 2.18 μs (0.00% GC)
median time: 2.29 μs (0.00% GC)
mean time: 2.43 μs (3.85% GC)
maximum time: 531.31 μs (98.95% GC)
Только ускорение в 2,5 раза. Функция replace
очень хорошо реализована!
Другим способом перехода без регулярного выражения является
join((SubString(seq,i,i+9) for i=1:10:length(seq)),'\n')
Это не так быстро (на 10 раз медленнее, без ограничения на распределение памяти на моей машине), но очень читаемо.
Ответ 3
Что-то вроде:
julia> split(replace(seq, r"(.{10})", s"\1 "))
6-element Array{SubString{String},1}:
"MSKNKSPLLN"
"ESEKMMSEML"
"PMKVSQSKLN"
"YEEKVYIPTT"
"IRNRKQHCFR"
"RFFPYIALFQ"
Если вы хотите использовать его как строку, используйте join()
:
julia> join(split(replace(seq, r"(.{10})", s"\1 ")), "\n")
"MSKNKSPLLN\nESEKMMSEML\nPMKVSQSKLN\nYEEKVYIPTT\nIRNRKQHCFR\nRFFPYIALFQ"
julia> println(ans)
MSKNKSPLLN
ESEKMMSEML
PMKVSQSKLN
YEEKVYIPTT
IRNRKQHCFR
RFFPYIALFQ
Ответ 4
Я не знаю, как вы можете сделать с REGEX, но я думаю, что он может решить вашу проблему:
a = "oiaoueaoeuaoeuaoeuaoeuaoteuhasonetuhaonetuahounsaothunsaotuaosu"
last = 0
#create the interval, in your case 10
salt = 10
#iterate in string (starts in the 10th value, don't forget julia use 1 to first index)
for i in salt:salt+1:length(a)
# replace the string for a new one with '\n'
a = string(a[1:i], '\n', a[i+1:length(a)])
last = Int64(i)
end
# replace the rest
a = string(a[1:length(a) - last % salt + 1], '\n', a[length(a) - last % salt + 2:length(a)])
println(a)