MATLAB: How to replace a loop with arrayfun – problems with strrep

arrayfunMATLABstrrep

Hi, I am trying to replicate the behavior of a loop using arrayfun, but running into problems. The loop that is working looks as follows:
nodes1 ={'RB_AA_AL_CTA'; 'RB_AA_AL_HDGE'; 'RB_AA_CA'; 'RB_AA_EH'; 'RB_AA_EQ_DMLC_EUR'; 'RB_AA_EQ_DMLC_USD'; 'RB_AA_EQ_DMLC_JPY';};
for jj = 1:length(nodes1)
ix_ = find(nodes1{jj}=='_');
if length(ix_) >= 3
nodes1{jj}(ix_(3:end)) = '-';
end
end
The code is trying to achieve the following: It replaces all _ underscores after the 3rd underscore for all entries in nodes1.
I would like to figure out how to translate the loop to an arrayfun. This is the code that I have so far:
nodes2 ={'RB_AA_AL_CTA'; 'RB_AA_AL_HDGE'; 'RB_AA_CA'; 'RB_AA_EH'; 'RB_AA_EQ_DMLC_EUR'; 'RB_AA_EQ_DMLC_USD'; 'RB_AA_EQ_DMLC_JPY';};
lNode=length(nodes2);
temp = arrayfun(@(x) find(nodes2{x}=='_'),1:lNode,'un',false);
temp2 = arrayfun(@(x) length(temp{x}),1:lNode);
temp3 = arrayfun(@(x) temp{x}(3:end),1:lNode,'un',false);
%temp4 = arrayfun(@(x) nodes2{x}(temp3{x})='-',1:lNode,'un',false);
temp4 = arrayfun(@(x) strrep(char(nodes2{x}(temp3{x})),'_','-'),1:lNode,'un',false);
The commented out %temp4 line gives me an error as I am not allowed to use an = sign in the arrayfun function. If I would run:
nodes2{1}(temp3{1})='-'
by itself, then this syntax would give me exactly what I want. My first thought was to then use strrep (last row of code), but even though the code executes, it doesn't replace the _ underscore in nodes2.
Any idea how I can get this to work with arrayfun? Why isn't my approach working? I would like to understand the underlying problem.
Thanks
Sven

Best Answer

Hi Sven (congrats on the name),
Here's a pretty direct way to do what you're trying to do. It uses regexp once and cellfun once:
nodes1 ={'RB_AA_AL_CTA'; 'RB_AA_AL_HDGE'; 'RB_AA_CA'; 'RB_AA_EH'; 'RB_AA_EQ_DMLC_EUR'}
% Split each string into the first 3 underscores (tok1) and the rest (tok2)
toks = regexp(nodes1,'(.*?_){3}(.*)','tokens','once');
% Find which strings might actually need replacement
mask = ~cellfun(@isempty,toks);
% Perform replacement on tok2 only and merge it to unreplaced tok1
result = nodes1;
result(mask) = cellfun(@(tok)[tok{1} strrep(tok{2},'_','-')],toks(mask),'Un',0);
Did that help you out?
Thanks, Sven.