how to vectorize this string split function in Matlab - matlab

How can I vectorize this strsplit function in Matlab so that it runs faster? Thank you
function parts = strsplit(splitstr, str)
splitlen = length(splitstr);
k = strfind(str, splitstr);
parts = cell(length(k)+1, 1);
s = 1;
if isempty(k)
parts{1} = str;
return
end
for i=1:length(k)
parts{i} = str(s : k(i)-1);
s = k(i) + splitlen ;
end
parts{end} = str((k(end) + splitlen) : end);

You can replace your function by a call to TEXTSCAN.
str = 'testxyztest2xyztest3';
splitStr = 'xyz';
out = textscan(str,'%s','delimiter',splitStr,'multipleDelimsAsOne',1)
out{1}
ans =
'test'
'test2'
'test3'

You can use regexp (note also the example on string splitting on that page):
out = regexp(str, regexptranslate('escape', splitStr), 'split');
The regexptranslate function escapes the split string so that it gets treated as a literal string and not a regular expression.

Related

How to generalize Matlab function?

I have a Matlab function. I need to generalize this function. This code’s aim is to check this IndicMPs are in the TableTemp, if it is there, then we extract relevant age limits, such as: Age_Limite_DC, Age_Limite_IT, Age_Limite_Ch and Transfert_Prime_IT_DC. My idea is to generalize, passing parameters to find out the "Type_pret" is.(May be I'm wrong) Since I'm beginner to Matlab can someone help me to encode a more generic function that can be used in a more general context?
function Structure = optimisation_function()
Data = load('Data.mat');
Structure = Data.Structure;
TableTemp = Data.TableTemp;
Age_Limite_DC = zeros(size(Structure,1),1);
Age_Limite_IT = zeros(size(Structure,1),1);
Age_Limite_CH = zeros(size(Structure,1),1);
Transfert_Prime_IT_DC = zeros(size(Structure,1),1);
for IndexMPAL = 1 : length(Structure.AnneeSouscription)
% Determine Type_Pret (Loan Type)
if ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'A'))
Type_Pret = 'A';
elseif ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'B'))
Type_Pret = 'B';
elseif ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'C'))
Type_Pret = 'C';
elseif ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'D'))
Type_Pret = 'D';
elseif ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'E'))
Type_Pret = 'E';
end
MP_CP = Structure.NomCodeProduit(IndexMPAL);
MP_AnSous = Structure.AnneeSouscription(IndexMPAL);
MP_TypePret = Type_Pret;
IndicCP = strcmp(MP_CP, TableTemp.CodeProduit);
IndicAS = MP_AnSous== TableTemp.AnneeSouscription;
IndicTP = strcmp(MP_TypePret, TableTemp.TypePret);
IndicMP = IndicCP & IndicAS & IndicTP;
if ~any(IndicMP)
Msg = strcat('CodeProduct:',MP_CP{1}, ', Année Souscription:', num2str(MP_AnSous), ', Type Prêt:', MP_TypePret);
error('Error', Msg)
else
Age_Limite_DC(IndexMPAL,1) = TableTemp.Age_Limite_DC(IndicMP,1);
Age_Limite_IT(IndexMPAL,1) = TableTemp.Age_Limite_IT(IndicMP,1);
Age_Limite_CH(IndexMPAL,1) = TableTemp.Age_Limite_CH(IndicMP,1);
Transfert_Prime_IT_DC(IndexMPAL,1)=
TableTemp.Transfert_Prime_IT_DC(IndicMP,1);
end
end
Structure.Age_Limite_DC = Age_Limite_DC;
Structure.Age_Limite_IT = Age_Limite_IT;
Structure.Age_Limite_CH = Age_Limite_CH;
Structure.Transfert_Prime_IT_DC = Transfert_Prime_IT_DC;
end
The if/elseif can be simplified with a cell array:
liststr = {'A','BB','C','D','E'}; % builds a cell array, each cell contains a string
Positive_matches = strfind(liststr,Structure.Type_Pret{IndexMPAL}) % returns a list for each cell of the indices where the element was found (empty if none)
Index = find(~cellfun('isempty', Positive_matches )) % converts the previous list into a logical 0/1 array indicating whether an item was found (1) or not (0)
% if isempty(Index); continue; end % If no index is found, to avoid an error in the next instruction, skips the rest of the code.
Type_Pret = liststr(Index(1));
If the Type_Pret are the same in your list and in Structure? , you can usestrcmp`:
liststr = {'A','B','C','D','E'};
if any(strcmp(Structure.Type_Pret,liststr))
Type_Pret = Structure.Type_Pret
else
% handle error
end
You can also work directly on Structure.Age_Limite_DC without using Age_Limite_DC.

About save string inside an array

I have question about how can I get from a user multiple inputs(once per line) as a string and save it inside an array ?
I tried something like this :
function[str] = get_data()
st = '';
st{1} = input{'enter the first name','s'};
st{2} = input{'enter the first name','s'};
str = strings(st)
end
Declare your cell beforehand as a cell. Not as a string. Then you can fill it with the inputs.
function[str] = get_data()
st = cell(1,2);
st{1} = input('enter the first name','s');
st{2} = input('enter the last name','s');
str=[st{:}] %if you want to convert it back to a string
%str = strcat(st{1},'_',st{2}) %if you want a _ between the inputs
end
Try the following code:
st = [];
st{1} = input('enter the first name: ','s');
st{2} = input('enter the last name: ','s');
str = strcat(st{1},'_',st{2})

Matlab name assignment

I am trying to decrease some big chucks of matlab code i had from a while ago, and was hoping to get them a bit more "clean".
The VarName2,VarName3,VarName4 ...etc are provide by measured data and i will know what they are always going to be thus i gave me the name A,B ,C , the think i want changed though is the first part of the name, so every time i run the .m file I will use the input('') option
where as fname = 'SWAN' and A, B , C are the second part of the name and they are constant.
fname = input ('enter name')
fname_A = VarName2
fname_B = VarName3
fname_C = VarName4
and want to be getting
SWAN_A = VarName2
SWAN_B = VarName3
SWAN_C = VarName4
thank you
Following your advices I been trying the structure construction
S.name = input ('enter name of the data ".." ==')
S.A = A;
S.A(1,:)=[];
S.B = B;
S.B(1,:)=[];
S.C = C;
S.C(1,:)=[];
S.D = D;
S.D(1,:)=[];
S.E = E;
S.E(1,:)=[];
may i ask if i can also have an input thing command so i can change the name of the structure?
Precede the script with S='west' and then do
'S'.name = input ('enter name of the data ".." ==')
S.A = A;
Here is how I would probably store the information that you are handling:
S.name = input ('enter name')
S.A = VarName2
S.B = VarName3
S.C = VarName4
And if you want to do it a few times:
for t=3:-1:1
S(t).name = input ('enter name')
S(t).A = VarName2
S(t).B = VarName3
S(t).C = VarName4
end
In this way you could now find the struct named 'swan':
idx = strcmpi({S.name},'SWAN')
you can use eval
eval( sprintf('%s_A = VarName2;', fname ) );
eval( sprintf('%s_B = VarName3;', fname ) );
eval( sprintf('%s_C = VarName4;', fname ) );
Note that the use of eval is not recommended.
One alternative option may be to use struct with dynamic field names:
A.( fname ) = VarName2;
B.( fname ) = VarName3;
C.( fname ) = VarName4;
Now you have three structs (A, B and C) with A.SWAN equal to VarName2, B.SWAN equal to VarName3 etc.

For colon operator with char operands, first and last operands must be char

I have a Matlab code as you can see here :
function IWDalg(similarityMatrix,NumberOfSentencesInFile,NumberOfSentencesInAbstract)
NumIWDs = str2int(NumberOfSentencesInFile);
Numnodes=NumIWDs;
av = 1; bv = 0.01; cv = 1;
as = 1; bs = 0.01; cs = 1;
soil = repmat(InitSoil,Numnodes,Numnodes);
for i =1:NumIWDs
IWD{i}.vel = InitVel;
IWD{i}.tour = [];
IWD{i}.tour(1) =i;
IWD{i}.soil = 0;
end
I the loop for when the matlab tries to compile first line of For clause i got this error:
??? For colon operator with char operands, first and last operands must be char.
I am so beginner in matlab programming .
Best regards
Try this .
NumIWDs = str2double(NumberOfSentencesInFile);
You should convert char to double for executing for colon.

Matlab) what should I put more with function for, sttrep, cell?

I want to make the results like this:
phraseblanks
phrasemat = Hello and how are you?
Hi there everyone!
How is it going?
WHazzup?
Phrase 1 had 4 blanks
Phrase 2 had 3 blanks
Phrase 3 had 2 blanks
Phrase 4 had 0 blanks
New phrasemat is :
Hello&and&how&are&you?
Hi&there&everyone!
How&is&it&going?
WHazzup?
so I made script "phraseblanks.m":
phrasemat = char('Hello and how are you?', ...
'Hi there everyone!', 'How is it going?', 'WHazzup?')
[r, c] = size(phrasemat);
for i = 1:r
phrasemat_new = cell(r, c);
howmany = countblanks(phrasemat(i, :));
fprintf('Phrase %d had %d blanks\n', i, howmany);
phrasemat(i,:) = strrep(phrasemat(i,:),' ','&')
phrasemat_new{i,:} = [phrasemat(i,:)];
end
fprintf('Changing one is %s\n', eval('phrasemat_new'));
script "countblanks.m":
function num = countblanks(phrase)
% countblanks returns the # of blanks in a trimmed string
% Format: countblanks(string)
num = length(strfind(strtrim(phrase), ' '));
end
and I keep having errors.
please help me..
I modified slightly your phraseblanks.m so that it works.
phrasemat = {'Hello and how are you?', ...
'Hi there everyone!', ...
'How is it going?', ...
'WHazzup?'};
r = numel(phrasemat);
phrasemat_new = cell(1, r);
for i = 1:r
howmany = countblanks(phrasemat{i});
fprintf('Phrase %d had %d blanks\n', i, howmany);
phrasemat{i} = strrep(phrasemat{i}, ' ', '&');
phrasemat_new(i) = phrasemat(i);
end
fprintf('Changing one is %s\n', phrasemat_new{:});
Obviously it could be written in a nicer, more "matlaby-way", but I didn't want to stride too far from your original version. Also you could consider using regular expressions, since if you have to spaces next to each other and you want to treat them as one blank space.