function myFunc = executeCmdByKind(var1,kind)
switch kind
case 'open'
cmdToExecute = [''var1 '','' locationIs '',''clear''];
case 'close'
cmdToExecute = [''var1 '','' locationIs '',''delete''];
case 'move'
cmdToExecute = [''var1 '','' locationIs '',''move''];
end
a = system(cmdToExecute);
end
My question is : is there a better way "optimal" to write this code as I call the same cmdToExecute only the latest arg changes
Thanks,
Your syntax makes no sense to me, but I'll stick with it. You could streamline your code like this I guess:
function myFunc = executeCmdByKind(var1,kind)
switch kind
case 'open'
last = ''clear'';
case 'close'
last = ''delete'';
case 'move'
last = ''move'';
end
cmdToExecute = [''var1 '','' locationIs '', last];
There are, as always, several ways of doing it. I'd do it like the following:
function myFunc = executeCmdByKind(var1,kind)
a = {'open', 'close', 'move'};
b = {'clear', 'delete', 'move'};
logi = ismember(a, kind);
cmdToExecute = [var1, locationIs, b{logi}];
That's not the nicest code, but it's short, if you want that ;-)
First I look via kind which index it has in the vector a and after retreiving the index, I can then select the corresponding element from b :-)
Edit: Short and it's easily expandable in the future with more elements :-)
Related
I am working in Matlab. I have defined:
a(1).x=1;
a(1).y=2;
a(1).z.w=3;
a(2).x=4;
a(2).y=5;
a(2).z.w=6;
I am now trying to add the fields in the two structures a(1) and a(2) such that I get:
c.x = 5;
c.y = 7;
c.z.w = 9;
Any idea how I can do this in an elegant way? Note that in the original problem the structures have many more fields (around 50).
Thank you very much in advance!
José
Here is a solution, for any depth of struct
The code of the script (or MATLAB command)
a(1).x=1;
a(1).y=2;
a(1).z.w=3;
a(2).x=4;
a(2).y=5;
a(2).z.w=6;
c=a(1);
c = returnStruct(c, a(2));
%{
you can also sum any amount of structs
for i=2:length(a)
c=returnStruct(c, a(i));
end
%}
with the recursive function
function rs = returnStruct(s,a)
fn = fieldnames(s);
for i=1:length(fn)
if isstruct(s.(fn{i}))
s.(fn{i}) = returnStruct(s.(fn{i}), a.(fn{i}));
else
s.(fn{i}) = s.(fn{i})+a.(fn{i});
end
end
rs = s;
end
I tested it for deeper levels of structs and it worked perfectly. Maybe, you have to adapt it slightly for your case, but this should be the way to go.
Unfortunately, any function like struct2cell only converts the first level, so you need something else.
If the deepest substructure level is 2 then this code will work:
fields=fieldnames(a);
for i=1:numel(fields)
if isstruct(a(1).(fields{i}))
fields2=fieldnames(a(1).(fields{i}));
for j=1:numel(fields2)
a(3).(fields{i}).(fields2{j})= a(1).(fields{i}).(fields2{j})+a(2).(fields{i}).(fields2{j});
end
else
a(3).(fields{i})=a(1).(fields{i})+a(2).(fields{i});
end
end
You can have a simple recursive solution
function r = sumfields(s)
if isstruct(s)
for f = fieldnames(s).'
r.(f{1}) = sumfields([s.(f{1})]);
end
else
r = sum(s);
end
end
Is there a way here to write more efficient, more generic code?
As the value return doesn't change, do I need a switch here?
function result = whichValue(value)
switch value
case 'green_ok'
result = 'green&ok';
case 'green_ko'
result = 'green&ko';
case 'green_check'
result = 'green&check';
end
end
This seems like a poor way of doing things, but seems to work for your examples:
result=value
value(value=='_')='&'
How about using strsplit:
value_split = strsplit(value, '_');
result = [value_split{1}, '&', value_split{2}]
I've did my code like that :
r= randper(3)
switch num2str(r(i))
case '1' F1=func1(var1);
case '2' F2=func2(var2);
case '3' F3=func3(var3);
otherwise disp('error');
end
In Matlab, i coudn't find the way to concatenate r with "func" and that could e read as a function not as string
Usually in other langage I could do it like that (it's just an example)
r= randper(3)
F+r(i)=func+r(i)(var+r(i))
Q: How could I shorten my code in one line ?
Thanks !
Ok, there's two ways of doing this: the quick way, and the nice way.
The quick way uses eval which evaluates a string as though it were m-code.
r= randper(3)
eval('F' + num2str(r(i)) + ' = func' + r(i) + '(var' + r(i) + ')');
The nice way creates an array of function pointers and then calls those:
func{1} = #func1;
func{2} = #func2;
func{3} = #func3;
r = randperm(3);
F{r(i)} = func{r(i)}(var(r(i)));
The above method helps avoid the myriad of issues that can crop up when you have used eval.
I'm making a generic subsref for my classA, which has an attribute attrA that is a classB instance.
So far, it's working, it lets me do things like
x = objA.attr1.methB(),
which was what I was trying to do to do in the first place.
function this = Class1(varargin)
this.attrA = ClassB()
this = class(this,'ClassA')
function this = ClassB()
this.AttrB1 = 'valueB1'
this.AttrB2 = 'valueB2'
function out = methB
out = this.AttrB2
The problem I stumbled upon is this:
when the call to a method is executed in my subsref, I do it like this (detecting that it's a method etc is done before):
methName = index(1).subs;
args = index(2).subs;
if iscell(args)
varargout = {feval(methName,this,args{:})};
else
varargout = {feval(methName,this,args)};
end %end if iscell
The problem is that when the methName method supports variable number of outputs, this varargout is not equivalent to [x,y,...] (the number of outputs should be assigned in the call to subsref, so methName always returns a single output, which is not always what I want (almost, but not always).
How would I let methName know how many outputs I want? (I don't want to have to pass N as a parameter).
I'm thinking something like creating a string str='[out1,out2,out3...]'
and then doing something like
eval([
str ...
'= {feval(methName,this,args{:})};'...
])
But I keep thinking there must be a more elegant way of doing it.
If the number of outputs you expect is dependent on the output arguments requested from your subsref, you can simply use nargout like this:
[varargout{1:nargout}] = feval(methName,this,args{:});
This solution worked, but I needed to add a little something for single outputs:
if iscell(args)
[argout{:}] = feval(methName,this,args{:});
else
[argout{:}]= {feval(methName,this,args)};
end %end if iscell`
if isSingleCell(argout) && iscell(argout{1})`
v = argout{1};
argout{1}=v{1};
end
I'm not sure, but it may be that the last bit was only necessary to fix something else ( I had to fix a lot of other things to make this work). I'll get back to it when I finish what I was trying to do with this class
I have a matlab structure array Modles1 of size (1x180) that has fields a, b, c, ..., z.
I want to understand how many distinct values there are in each of the fields. i.e.
max(grp2idx([foo(:).a]))
The above works if the field a is a double. {foo(:).a} needs to be used in the case where the field a is a string/char.
Here's my current code for doing this. I hate having to use the eval, and what is essentially a switch statement. Is there a better way?
names = fieldnames(Models1);
for ix = 1 : numel(names)
className = eval(['class(Models1(1).',names{ix},')']);
if strcmp('double', className) || strcmp('logical',className)
eval([' values = [Models1(:).',names{ix},'];']);
elseif strcmp('char', className)
eval([' values = {Models1(:).',names{ix},'};']);
else
disp(['Unrecognized class: ', className]);
end
% this line requires the statistics toolbox.
[g, gn, gl] = grp2idx(values);
fprintf('%30s : %4d\n',names{ix},max(g));
end
Indeed, there is a better way. Surprisingly, MATLAB allows you to access the struct fields using a key string without eval, for instance:
Models1(1).(names{ix})
so instead, you can write this:
className = class(Models1(1).(names{ix});
...
values = [Models1(:).(names{ix})];
...
values = {Models1(:).(names{ix})};
Also, instead of using class and strcmp, you can just test the same conditions with isa:
v1 = Models1(1).(names{ix});
if (isa(v1, 'double') || isa(v1, 'logical'))
values = [Models1(:).(names{ix})];
% # ...
elseif (isa(v1, 'char'))
values = {Models1(:).(names{ix})};
% # ...
else
disp(['Unrecognized class: ', class(v1)]);
end
It should be much faster.