Parse function parameters using InputParser class with unknown number of parameters and optional name-value pairs parameters
39 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Bob Randall
el 23 de Oct. de 2024 a las 17:58
Respondida: Shlok
el 1 de Nov. de 2024 a las 4:20
Hi Community,
What would it be the right way to parse a function with inputParser class that accepts an aribitrary number of parameters assigned through the usual varargin with some optional name-value pairs parameters?
This example showing two different function calls of vprintf should illustrate the problem:
verbosity = 2;
vprintf(verbosity, "onNewLine", true, "this is a string: '%s', and this is a number: '%g'\n", "tuna" , 100.1);
vprintf(verbosity, "this is a string: '%s', and this is a number: '%g'\n", "tuna" , 100.1);
where:
- verbosity is mandatory,
- onNewLine name with its following value true are optional ,
- and everything after is essentially optional.
This crude attempt did't work because the parser seems to accept name-value pairs arguments only:
function vprintf(verbosity, varargin)
p = inputParser;
addOptional(p,'onNewLine', 0);
parse(p, varargin{:});
disp(p.Results);
end
And it gives the following error
vprintf(1,"onNewLine", true, "aaaaaaaaaaa");
Error using vprintf (line 4)
'aaaaaaaaaaa' is not a recognized parameter.
0 comentarios
Respuestas (2)
Raghava S N
el 28 de Oct. de 2024 a las 5:12
Hi,
From my understanding, you want to use a variable number of optional parameters without having explicitly declared them in the input parser. And you want these arbitrary number of parameters assigned through the “varargin” functionality.
The “KeepUnmatched” property of the “inputParser” is a matching indicator that throws an error when an input is not found in the input parser scheme. By default, the parse function throws an error if an input argument name does not match one defined in the input parser scheme.
To suppress the error and store the input argument name and value, set “KeepUnmatched” to “true” (or “1”). The “inputParser” object stores unmatched input argument names and values in the “Unmatched” property. Refer to this link for more details about this property - https://www.mathworks.com/help/matlab/ref/inputparser.html#:~:text=KeepUnmatched%20%E2%80%94%20Matching%20indicator.
Here is some example code to illustrate this functionality –
function p = vprintf(verbosity, varargin)
p = inputParser;
p.KeepUnmatched=true;
addOptional(p,'onNewLine', 0);
parse(p, varargin{:});
disp("Result property")
disp(p.Results)
disp("Unmatched property")
disp(p.Unmatched);
end
p = vprintf(1,"onNewLine", true, "aaaaaaaaaaa", 6);
For additional reference please, refer to this MATLAB Answer post that discusses the “KeepUnmatched” property in detail - https://www.mathworks.com/matlabcentral/answers/395295-allowing-unknown-parameters-in-an-inputparser.
Hope this helps!
1 comentario
Shlok
el 1 de Nov. de 2024 a las 4:20
Hi Bob,
The “inputParser” function does supports passing arbitrary number of parameters and then name-value pairs, but those parameters need to be explicitly specified within the parsing function. Since the non-name-value pair parameters are not exhaustive, it becomes difficult to differentiate them with name-value pairs and hence parsing them requires a different approach.
Hence, to parse appropriately, you can specify the number of name-value pairs as a required argument (say “numNameValuePairs”). And then pass name-value pairs, followed by the optional parameters. Within the parsing function, name-value pairs can be separated out from “varargin” array using the previously supplied total count, and thus can be parsed using “inputParser”. Remaining arguments can be extracted using indexing from “varargin” array.
I have written a sample code that does the same:
% verbosity - taken from your example
% numNameValuePairs – numeric input, gives the count of name-value pairs
function vprintf(verbosity, numNameValuePairs, varargin)
p = inputParser;
% Loop through varargin to separate name-value pairs from remaining arguments
i = 1;
while i <= numNameValuePairs * 2
if (ischar(varargin{i}) || isstring(varargin{i})) && i < length(varargin) && (islogical(varargin{i+1}) || isnumeric(varargin{i+1}) || ischar(varargin{i+1}) || isstring(varargin{i+1}))
addParameter(p, varargin{i}, varargin{i+1})
i = i + 2;
else
error('Expected name-value pairs are not correctly formatted.');
end
end
% Parse the name-value pairs
parse(p, varargin{1:numNameValuePairs * 2});
% Extract the remaining arguments
remainingArgs = varargin(numNameValuePairs * 2 + 1:end);
fprintf('Verbosity: %d\n', verbosity);
disp('Parsed name-value pairs:');
disp(p.Results);
fprintf('Remaining arguments: ');
disp(remainingArgs);
end
verbosity = 2;
numNameValuePairs = 1;
vprintf(verbosity, numNameValuePairs, "onNewLine", true, "this is a string: '%s', and this is a number: '%g'\n", "tuna" , 100.1);
vprintf(verbosity, numNameValuePairs, "onNewLine", true);
vprintf(1, numNameValuePairs, "onNewLine" , true, "%d, %f, %s %d %d\n", 10, 123.4, "string", 1,2);
Thus, the above code parses both name-value pairs and additional parameters supplied in the function.
You can refer to the following MathWorks Documentation link to know more about “inputParser” function:
0 comentarios
Ver también
Categorías
Más información sobre Argument Definitions en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!