Interpreting varargin name-value pairs.

50 vues (au cours des 30 derniers jours)
Chad Greene
Chad Greene le 1 Mai 2014
I've been writing a lot of functions lately. I like allowing the user to declare options in my functions using name-value pairs, but I have not found a good clean method of interpreting varargin. Here are two methods I tend to use, but both feel a bit clunky:
% Method 1:
for k = 1:length(varargin)
if strcmpi(varargin{k},'fontname')
fontname = varargin{k+1};
varargin{k+1}=[];
varargin{k}=[];
end
end
% Method 2:
nk = 1:length(varargin);
for k = 1:length(varargin)
if strcmpi(varargin{k},'fontsize')
fontsize = varargin{k+1};
nk(k:k+1) = [];
end
end
varargin = varargin(nk);
Is there a better standard procedure for interpreting a list of varargin arguments?

Réponse acceptée

Sean de Wolski
Sean de Wolski le 1 Mai 2014
Yes... Use inputParser
  8 commentaires
Chad Greene
Chad Greene le 1 Mai 2014
Sean: the inputParser looks promising, especially for a long list of possible inputs. If I were using it to get font name and size from a list of varargin it'd look like this :
p = inputParser;
defaultFontSize = 12;
defaultFont = 'times';
addParamValue(p,'font',defaultFont,@ischar);
addParamValue(p,'fontsize',defaultFontSize,@isnumeric);
parse(p,varargin{:});
font = p.Results.font;
fontsize = p.Results.fontsize;
Above I've used addParamValue instead of the recommended addParameter because R2012b does not recognize addParameter. Now, is there a way to keep track of which varargin arguments have been evaluated? In the original post I had lines that delete names and values from varargin because at the end of the function sometimes I like to put all the leftover varargin arguments into a function. For example,
function [h] = myfunction( varargin )
% Parse inputs:
p = inputParser;
defaultFontSize = 12;
defaultFont = 'times';
addParamValue(p,'font',defaultFont,@ischar);
addParamValue(p,'fontsize',defaultFontSize,@isnumeric);
parse(p,varargin{:});
font = p.Results.font;
fontsize = p.Results.fontsize;
% use leftover varargin:
h = plot(1:10,11:20,varargin{:});
text(5,14,'this is my text','fontsize',fontsize)
end
The function above does not work, but it's a design that I would like to get to work. I'd like to let the user create some plot with any plot options and format the text with a command like
myfunction('linewidth',5,'fontsize',30)
Cedric
Cedric le 2 Mai 2014
Modifié(e) : Cedric le 2 Mai 2014
Hi Chad, almost there, look at the KeepUnmatched and Unmatched properties of the parser. You might also be interested in functions fieldnames and struct2cell if you want to build a comma separated list for passing unmatched param/values further.

Connectez-vous pour commenter.

Plus de réponses (3)

Kevin Schroeder
Kevin Schroeder le 20 Juil 2021
If it is of any value to others, I have always used a switch case nested in a for loop.
function myFunction(varargin)
for setting = 1:2:nargin
switch varargin{setting}
case 'SettingName1'
value = varargin{setting + 1}
[]; %do stuff with value
case 'SettingName2'
value = varargin{setting + 1}
[]; %do stuff with value
case 'SettingName3'
value = varargin{setting + 1}
[]; %do stuff with value
otherwise
[];
end
end
end
Functionally it should be similar to the nested if statements, but it looks much cleaner.

Justin
Justin le 1 Mai 2014
I'm always a fan of cellfun.
inputExist = find(cellfun(@(x) strcmpi(x, 'fontname') , varargin));
if inputExist
fontsize = varargin{inputExist+1};
end
I have used this or something similar before. You can wrap this in a for loop that goes through your expected inputs and instead of assigning them directly to fontsize you could assign it to a structure like:
inputs.(currentName) = varargin{inputExist+1};
Let me know if that makes sense.
  1 commentaire
Cedric
Cedric le 2 Mai 2014
Modifié(e) : Cedric le 2 Mai 2014
STRCMPI does work on cell arrays, so there is no need to use CELLFUN. Yet, it is likely not to be suited here, because Chad would have to test for all possible parameter names for both the function and the internal function. Using the parser and its Unmachted property is more flexible for this reason.

Connectez-vous pour commenter.


Alexander
Alexander le 17 Juil 2016
Dont use inputParser if you need to codegen - it is not supported in R2016a.
  1 commentaire
Sean de Wolski
Sean de Wolski le 19 Juil 2016
With codegen, you won't be using variable number of inputs since everything needs to be defined.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Argument Definitions dans Help Center et File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by