Как мне использовать inputParser MATLAB с необязательными строковыми входами? В документации написано "использовать функцию проверки", но неясно, как это сделать
У меня есть файл MATLAB, который содержит одну функцию верхнего уровня, называемую sandbox
, Эта функция в свою очередь содержит две вложенные функции, mysum
а также myprod
, которые идентичны по функциональности и какие параметры они допускают, кроме того, что используется @sum
внутренне и другое использование @prod
внутренне. Моя цель - создать функцию-обертку для использования в обоих mysum
а также myprod
это берет на себя всю проверку и ввод данных. Эта функция называется applyFunc
,
Вот где это становится сложным. mysum
а также myprod
прийти в двух формах:
mysum(v)
возвращаетсяsum(v, 1)
,mysum(v, 'imag')
возвращаетсяsum(v, 1) + 1i
Любые другие комбинации ввода должны выдавать ошибку.
У меня проблемы с использованием inputParser
для анализа этих различных комбинаций ввода, в частности, необязательный ввод строки. Вот код:
function sandbox()
%% Data
v = [1 4; 3 3];
%% Calculations
s = mysum(v);
si = mysum(v, 'imag');
p = myprod(v);
pi = myprod(v, 'imag');
%% Accuracy tests
assert(isequal(s, [4 7]))
assert(isequal(si, [4+1i 7+1i]))
assert(isequal(p, [3 12]))
assert(isequal(pi, [3+1i 12+1i]))
function x = mysum(varargin)
x = applyFunc(@sum, varargin{:});
end
function x = myprod(varargin)
x = applyFunc(@prod, varargin{:});
end
end
function x = applyFunc(func, varargin)
p = inputParser();
p.addRequired('func', @(x) validateattributes(x, {'function_handle'}, {'scalar'}));
p.addRequired('v', @(x) validateattributes(x, {'double'}, {}, 'applyFunc:msg', 'v'));
p.addOptional('imag', '', @(x) validatestring(x, {'imag', ''})); % THIS LINE IS THE PROBLEM
p.parse(func, varargin{:});
f = p.Results.func;
v = p.Results.v;
strflag = p.Results.imag;
x = f(v);
if ~isempty(strflag)
validatestring(strflag, {'imag'});
x = x + 1i;
end
end
Строка, которая вызывает проблему, является следующей (как отмечено в коде выше):
p.addOptional('imag', '', @(x) validatestring(x, {'imag', ''}));
Документация для inputParser гласит:
Для необязательных строковых входов укажите функцию проверки. Без функции проверки входной синтаксический анализатор интерпретирует допустимые строковые входные данные как недопустимые имена параметров и выдает ошибку.
К сожалению, я понятия не имею, как это сделать. Есть что-то простое, что я пропускаю или что? Если 'imag'
аргумент не передается вообще (как в назначении s
а также p
), код работает нормально, но если я его передам, я получу эту ошибку:
Error using sandbox>applyFunc (line 32)
The value of 'imag' is invalid. It must satisfy the function:
@(x)validatestring(x,{'imag',''}).
Error in sandbox/mysum (line 18)
x = applyFunc(@sum, varargin{:});
Error in sandbox (line 7)
si = mysum(v, 'imag');
Любая помощь?
2 ответа
Проблема в том, что validatestring
возвращает соответствующую строку из аргумента ячейки ({'imag',''}
), а не логическое значение, указывающее, проходит ли оно проверку. Вместо этого используйте strcmp
а также any
:
@(x) any(strcmp(x,{'imag', ''}))
Кроме того, с validatestring
, если входная строка тоже не совпадает 'imag'
или же ''
(на самом деле просто 'imag'
поскольку пустые строки совпадают только в R2014a+), он выдаст ошибку, а не вернет false, чтобы inputParser
может вернуть соответствующую ошибку.
Еще один хороший способ решить эту проблему - изменить синтаксис applyFunc
полностью, чтобы вместо 'imag'
в качестве необязательного входного аргумента строки используйте параметр-значение с 'imag'
в качестве параметра и проверенного логического значения в качестве входных данных.
Определение ввода, предложенное Amro в комментариях:
p.addParameter('imag', false, @(x)validateattributes(x, {'logical'}, {'scalar'}))
Использование:
mysum(x,'imag',true)
mysum(x) % default is equivalent to mysum(x,'imag',false)
Это упростило бы остальную часть кода с p.Result.imag
быть logical
скаляр. Я бы предложил:
x = f(v) + p.Result.imag*1i;
Проблема не в inputParser
Я думаю, что проблема с validatestring
,
1) Сначала он не совпадает с пустыми строками:
>> x = ''
x =
''
>> validatestring(x, {'imag',''})
Expected input to match one of these strings:
imag,
The input did not match any of the valid strings.
Caused by:
Error using validatestring>checkString (line 85)
Expected input to be a row vector.
2) Во-вторых, если он успешно совпадает, он возвращает разрешенную строку (из одного допустимого выбора) вместо true/false. inputParser
требует, чтобы функция проверки либо возвращала логическое значение, либо ничего, но выдает ошибку при ошибке.