An efficient way to insert characters between other characters in a string

What is the efficient way in MATLAB to replace / insert one character (in a series of characters) with several others that match the one being replaced?

For example, consider the string Eq

: Eq = 'A*exp(-((x-xc)/w)^2)'

. Is there a way to replace *

with .*

, /

with ./

, \

with .\

and ^

with .^

without writing four separate lines strrep()

?

+3


source to share


3 answers


The function vectorize

already does almost everything you want, except that it doesn't convert mldivide

( \

) to ldivide

( .\

).

"Effectively", do you mean fewer lines of code or faster? Regular expressions are almost always slower than other approaches and less readable. I don't think they are necessary or a good choice in this case. If you only need to convert the string once, then the speed will be less than readability (it strrep

will still be faster). If you need to do this many times, this simple code you provided is 4-5 times faster than regexrep

for short strings like your example (and much faster for longer strings):

out = strrep(Eq,'*','.*');
out = strrep(out,'/','./');
out = strrep(out,'\','.\');
out = strrep(out,'^','.^');

      

If you want one line, use:



out = strrep(strrep(strrep(strrep(Eq,'*','.*'),'/','./'),'\','.\'),'^','.^');

      

which will also be slightly faster. Or create your own version vectorize

and call it.

If regular expressions shine in more complex cases, for example, if your line already partially vectorized: Eq = 'A.*exp(-((x-xc)/w)^2)'

. Even so, the function vectorize

simply uses strrep

and then calls strfind

to "remove any possible '..*'

, '../'

etc." and replace them with the correct atomic operators because they are faster (symbolic math strings can get very large, for example).

+1


source


Regular expressions will do the job nicely. Regular expressions just find patterns in the text. You specify what type of pattern you are looking for with a regex, and in the output, you will find the locations where the pattern occurred.

In our particular case, we not only want to find where patterns occur, we also want to replace those patterns with something else. In particular, use a function regexprep

from MATLAB to replace matches in a string with something else. Do you want to replace all the symbols *

, /

, \

and ^

adding .

in front of each.

The way it works regexprep

is the first input is the string you are looking at, the second input is the pattern you are trying to find. In our case, we want to find any of the *

, /

, \

, and ^

. To indicate this pattern, you put the desired characters in parentheses []

. Regular expressions are reserved \

as a special character to delineate characters that can be parsed as regular expressions, but in fact are not. Thus, for symbol \

and \^

for symbol ^

must be used \\

. The third input is that you want to replace every match. In our case, we just want to reuse every matching character, but we add.

at the start of the match. This is done using the \.$0

regular expression syntax. $0

means grabbing the first token created by the match ... which is essentially the matched character from the pattern. .

is also a reserved keyword using regular expressions, so we must add this character with a symbol \

.

Without further ado:

>> Eq = 'A*exp(-((x-xc)/w)^2)';
>> out = regexprep(Eq, '[*/\\\^]', '\.$0')

out =

A.*exp(-((x-xc)./w).^2)

      



Pattern that we're looking for [*/\\\^]

, which means that we want to find any of the *

, /

, \

- designated \\

in the regex, and \^

- designated as ^

the regular expression. We want to find any of these characters and replace them with the same symbol, adding to him a symbol .

- \.$0

.


As a more complex example, let's make sure to include all the symbols you're looking for in the sample equation:

>> A = 'A*exp(-((x-xc)/w)^2) \ b^2';
>> out = regexprep(A, '[*/\\\^]', '\.$0')

out =

A.*exp(-((x-xc)./w).^2) .\ b.^2

      

+3


source


I would go with regexp

like in Rayryeng's answer . But here's a different approach, just to provide an alternative.

ops = '*/\^';                          %// operators that need a dot
ii = find(ismember(Eq, ops));          %// find where dots should be inserted
[~, jj] = sort([1:numel(Eq) ii-.5]);   %// will be used to properly order the result
result = [Eq repmat('.',1,numel(ii))]; %// insert dots at the end
result = result(jj);                   %// properly order the result 

      

And option:

ops = '*/\^';                          %// operators that need a dot
ii = find(ismember(Eq, ops));          %// find where dots should be inserted
jj = sort([1:numel(Eq) ii-.5]);        %// dot locations are marked with fractional part
result = Eq(ceil(jj));                 %// repeat characters where the dots will be placed
result(mod(jj,1)>0) = '.';             %// place dots at indices with fractional part

      

+3


source







All Articles