How can I check whether an argument is given or not (inputParser)?

323 ビュー (過去 30 日間)
Ezor
Ezor 2016 年 12 月 14 日
編集済み: Leon 2024 年 2 月 26 日
Hi everyone,
I think the title is pretty obvious ! To be a little bit more precise, I'm using an InputParser to let the user choose what arguments (s)he wants to use. Therefore I would like to check what optional inputs have been enter or not. InputParser allows to enter name,value paire for each variable and I need something to check if a specific argument exists among all of those enter when the function is called.
It appears that 'isempty' doesn't work. I've also try this but it failed too
if varargin{:,1} == 'arg_name'
disp('ok')
else
disp('not ok')
end
(even if cell_structure(:,1)=='string' works outside a function)
Thanks in advance, Edward

回答 (5 件)

Sean de Wolski
Sean de Wolski 2016 年 12 月 14 日
編集済み: Sean de Wolski 2016 年 12 月 14 日
There's a 'UsingDefaults' property of the inputParser that is populated after it is parsed. This will tell you which variables are not using the default value.
  1 件のコメント
Ezor
Ezor 2016 年 12 月 14 日
I had not thought about that but I seems to be a good solution to bypass this issue. Thank you

サインインしてコメントする。


Guillaume
Guillaume 2016 年 12 月 14 日
Well, if the behaviour of your code is going to change depending on whether or not an optional input was given, then it's not really an optional input anymore.
inputParser does not offer the option of knowing which of the optional inputs were actually given. If you really need that, you're going to have to write your own input parser or reparse the optional parameters yourself.
  3 件のコメント
Guillaume
Guillaume 2016 年 12 月 14 日
編集済み: Guillaume 2016 年 12 月 14 日
function my_function(varargin)
valid_argnames = {'arg_name1', 'arg_name2', 'arg_name3'};
argwasspecified = ismember(valid_argnames, varargin(1:2:end));
%...
each element of argwasspecified is true if the corresponding element of valid_argnames is specified anywhere in the odd elements of varargin.
Note that ismember comparison is case sensitive. If you need case-insensitive you can wrap varargin(1:2:end) in lower.
Unlike inputParser, this does not support partial matches. This would require significantly more work.
edited: bug in indexing of varargin
Ezor
Ezor 2016 年 12 月 14 日
Thank you. That could do the trick. I'll try this and let you know if the ismember function suits my need.

サインインしてコメントする。


Ian
Ian 2018 年 12 月 5 日
A bit late to the game here, but expanding on Sean de Wolski's brief suggestion, here is a code snippet that should satisfy. This is essentially the inverse of Guillaume's approach -- test for the absence of a parameter in the UsingDefaults
function test_used(varargin)
p = inputParser;
addOptional(p,'opt1',[]);
addParameter(p,'arg1',[]);
addParameter(p,'arg2',[]);
parse(p,varargin{:});
if (~ismember('opt1',p.UsingDefaults)), fprintf('opt1 present\n'); end
if (~ismember('arg1',p.UsingDefaults)), fprintf('arg1 present\n'); end
if (~ismember('arg2',p.UsingDefaults)), fprintf('arg2 present\n'); end
end
and showing results:
>> test_used(10)
opt1 present
>> test_used(10,'arg2','goodbye')
opt1 present
arg2 present
>> test_used('arg1','hello')
arg1 present
This is similar to Guillaume's solution above, which is also good, but won't work if you have optional positional parameters (addOptional(...) ) or if the parser's StructExpand it set to true.
For those curious why this is needed, or at least useful: it allows setting related parameters when an optional or key/value pair is specified, without overriding a user setting. For example, I might want to set arg2 to arg1's value if the user specifies arg1 only, but keep the user's arg2 setting if both arg1 and arg2 are passed in.
  1 件のコメント
Maikel Zhilin
Maikel Zhilin 2022 年 12 月 26 日
This < > helped me, thank you :)
< ~ismember('arg1',p.UsingDefaults) >

サインインしてコメントする。


KSSV
KSSV 2016 年 12 月 14 日
function Hello(varargin)
if nargin==1
disp('Okay')
else
disp('not okay')
end
It takes any inputs, for one input it says ok for other inputs it says not ok.
  4 件のコメント
Ezor
Ezor 2016 年 12 月 14 日
編集済み: Ezor 2016 年 12 月 14 日
Maybe, but in that case there is something I don't understand. The code you gave me counts the arguments, but in my case, I don't know which one will be entered in 1st position and 2nd position. I'd like to dertermine if a given string my_target belongs to a list/array/cell array ('arg_name1','arg_name2')
KSSV
KSSV 2016 年 12 月 15 日
function Hello(varargin)
N = nargin ;
inputs = cell(N,1) ;
for i = 1:N
inputs{i} = varargin{i} ;
class(inputs{i})
end
Call it by Hello('Distance',3,'Velocity',{5})
Function will tell the classes of the inputs. Depending on your usage, you can code in the way you want.

サインインしてコメントする。


Leon
Leon 2024 年 2 月 25 日
Is there any reason not to use exist("arg_name", "var") ? It doesn't give a false positive for a global of the same name.
Maybe it would be too slow if you are calling the function many times per second.
  2 件のコメント
Walter Roberson
Walter Roberson 2024 年 2 月 25 日
The context is the parser for name/value pairs. The pseudo-variable that gets coded to "absorb" those is varargin . If varargin has been declared in the function header, then it will always exist for exit("varargin", "var") purposes -- it might just be empty if no name/value pairs were entered.
Leon
Leon 2024 年 2 月 26 日
編集済み: Leon 2024 年 2 月 26 日
Sorry, you're right. I thought you would be able to check for the existence of the actual individual argument by name, but it looks like Matlab's approach will force it to exist with its default value – you can't just let it not exist. My bad.
Another option would be to set a dummy default value such as "Not set" and check for that (and Matlab lets it be something that would fail the validation, so you can usually avoid using something that could be a valid input) but the UsingDefaults is obviously a much better approach.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeArgument Definitions についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by