How do I use a struct as a function input?

2 views (last 30 days)
I have a function that accepts up to 4 strings(they are 'rule1Before, rule1After, etc.' below) and in the the function these strings are set to struct values. In stead of hard coding these rules I would like to have one input, perhaps rules and then proceed as below. Any suggestions on how to handle this scenario? Thanks in advance!
function axiomGrowth = LsysExpand(rule1Before,rule1After,rule2Before,rule2After)
% LsysExpand: Expands from starting seed based on given parameters
% Inputs:
% numberOfIterations: number of times rules are applied
% axiom: the initial point from which growth occurs
% rule1Before: intital condition for rule 1
% rule1After: if rule1Before exists apply rule1After
% ...
% substituion rules
rule(1).before = rule1Before;
rule(1).after = rule1After;
% The arguments below are optional.
if nargin > 4
rule(2).before = rule2Before;
rule(2).after = rule2After;
end
  1 Comment
Stephen23
Stephen23 on 13 Apr 2017
Note to others: Do not use the accepted answer: it is buggy and very inefficient. See my answer for a much simpler, neater, and more efficient solution.

Sign in to comment.

Accepted Answer

mars
mars on 31 Jan 2017
Edited: mars on 4 Feb 2017
rulesParsed = repmat(struct('before', {} ,'after', {} ), 2, 10);
ruleTracker = 1;
for i=1:length(rules)/2
if (mod(i,2)~=0)
rulesParsed(i).before = cellstr(rules(ruleTracker));
rulesParsed(i).after = cellstr(rules(ruleTracker+1));
ruleTracker=ruleTracker+2;
end
if (mod(i,2)==0)
rulesParsed(i).before = cellstr(rules(ruleTracker));
rulesParsed(i).after = cellstr(rules(ruleTracker+1));
ruleTracker=ruleTracker+2
end
end
  2 Comments
Stephen23
Stephen23 on 4 Feb 2017
Edited: Stephen23 on 13 Apr 2017
This code has many bugs, and does not do what the author thinks it is doing: see my answer for a much more efficient solution.
For example the very first line seems to be an attempt at preallocating the output structure. However it does not work because the output structure is still empty:
>> repmat(struct('before', {} ,'after', {} ), 2, 10)
ans =
0x0 struct array with fields:
before
after
This means that the (initially empty!) structure will get expanded on each iteration: not an efficient use of memory. Also note that the author tries to preallocate to a different shape than the final output anyway (output is 3x1).
Then this code unnecessarily puts every string into a cell array:
>> tmp = rulesParsed(2).before
tmp =
'bef2'
>> class(tmp)
ans =
cell
>> tmp{1}
ans =
bef2
Why these 1xN chars are pointlessly put into cell arrays is not explained anywhere.
See my answer for a one line solution without all of these loops, ifs, bugs, pointless cell arrays, and inefficiency.
Guillaume
Guillaume on 4 Feb 2017
Edited: Guillaume on 6 Feb 2017
Other issues:
if somecond
dosemething
end
if ~samecond
dosomethingelse
end
is better written as
if somecond
dosomething
else
dosomethingelse
end
But in this case, dosomething and dosomething else are identical, so the if serve no purpose.

Sign in to comment.

More Answers (1)

Stephen23
Stephen23 on 4 Feb 2017
Edited: Stephen23 on 4 Feb 2017
Assuming that rules is a cell array of strings, then you just need this:
>> rules = {'bef1','aft1','bef2','aft2','bef3','aft3'};
>> rulesParsed = struct('before',rules(1:2:end),'after',rules(2:2:end))
That is all. Now lets test it:
>> rulesParsed(2).before
ans =
bef2
>> rulesParsed(2).after
ans =
aft2
Perfect. It produces the same structure as the OP's self-accepted answer, containing the same data. Just simpler, faster, and neater.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!