我正在为plot
编写一个包装器,它可以自动完成我经常做的一些任务。
示例代码段可能看起来像
function myplot(x,y,varargin)
plot(x,y,varargin{:})
xlabel('x axis')
ylabel('y axis')
end
我正在使用Matlab的varargin
将其他参数传递给plot
。但是,我发现我可能想在varargin中传递自己的可选参数。例如,我可能想写类似
>> myplot(1:10, 1:10, 'r', 'LineWidth', 2, 'legend', {'Series 1'})
让函数自动在图中包含一个图例 - 也就是说,我希望能够将我自己的关键字参数与您可以提供给图表的参数混合。如果没有为我的varargs编写完整的解析器,有没有办法在Matlab中简单地重复使用?
我尝试使用inputParser
对象,但这需要我手动添加每个可能的附加参数到绘图(以及它的默认值),这似乎并不理想。
答案 0 :(得分:6)
inputParser
可能仍然是最佳选择。您可以为其他参数构造对象,并将要传递给plot
的所有parameterName / parameterValue对转换为Unmatched
。
function myplot(x,y,varargin)
parserObj = inputParser;
parserObj.KeepUnmatched = true;
parserObj.AddParamValue('legend',false);
%# and some more of your special arguments
parserObj.parse(varargin);
%# your inputs are in Results
myArguments = parserObj.Results;
%# plot's arguments are unmatched
tmp = [fieldnames(parserObj.Unmatched),struct2cell(parserObj.Unmatched)];
plotArgs = reshape(tmp',[],1)';
plot(x,y,plotArgs{:})
xlabel('x axis')
ylabel('y axis')
if myArguments.legend
%# add your legend
end
end
答案 1 :(得分:1)
为了支持Linespec参数而不干扰名称为4个字符或更少的输入解析器参数(例如,' grid'或' bins'),你应该稍微更复杂的方法来检查Linespec参数的有效性而不是' @(x)ischar(x)&& numel(x)< = 4'。对于' grid'这个检查也会返回true。和' bins',虽然它们不是有效的Linespec参数。
仅当输入了有效的Linespec参数时,以下函数才会返回true:
function isls = islinespec(x)
isls = false;
if ~ischar(x)
return;
end
lineStyleSpecifiers = {'--','-.','-',':'};
markerSpecifiers = {'square','diamond','pentagram','hexagram','+','o','*','.','x','s','d','^','v','>','<','p','h'};
colorSpecifiers = {'r','g','b','c','m','y','k','w'};
for oo=1:length(lineStyleSpecifiers)
k = strfind(x,lineStyleSpecifiers{oo});
if ~isempty(k)
x(k:(k+length(lineStyleSpecifiers{oo})-1)) = [];
break;
end
end
for oo=1:length(markerSpecifiers)
k = strfind(x,markerSpecifiers{oo});
if ~isempty(k)
x(k:(k+length(markerSpecifiers{oo})-1)) = [];
break;
end
end
for oo=1:length(colorSpecifiers)
k = strfind(x,colorSpecifiers{oo});
if ~isempty(k)
x(k:(k+length(colorSpecifiers{oo})-1)) = [];
break;
end
end
if isempty(x)
isls = true;
end
(不可否认,使用正则表达式可以更好地编写函数,但它可以解决问题。)
使用示例:
parserObj = inputParser;
parserObj.KeepUnmatched = true;
parserObj.AddParamValue('legend',false);
parserObj.AddParamValue('grid',true);
parserObj.addOptional('LineSpec','-', @(x) islinespec(x));
答案 2 :(得分:0)
要使用解析器以明确的w / param / val对的方式添加对LineSpec的支持,请执行以下操作:
function myplot(x,y,varargin)
parserObj = inputParser;
parserObj.KeepUnmatched = true;
parserObj.AddParamValue('legend',false);
parserObj.addOptional('LineSpec','-',@(x) ischar(x) && (numel(x) <= 4));
%# and some more of your special arguments
parserObj.parse(varargin{:});
%# your inputs are in Results
myArguments = parserObj.Results;
%# plot's arguments are unmatched
plotArgs = struct2pv(parserObj.Unmatched);
plot(x,y,myArguments.LineSpec,plotArgs{:})
xlabel('x axis')
ylabel('y axis')
if myArguments.legend
%# add your legend
end
end
function [pv_list, pv_array] = struct2pv (s)
p = fieldnames(s);
v = struct2cell(s);
pv_array = [p, v];
pv_list = reshape(pv_array', [],1)';
end