我正在尝试构建自己的MATLAB dir
函数版本。我当前的代码(下面)几乎可以工作,但我在解析某个输入组合时遇到了问题。
我希望它能做到这一点:
为了更清楚,我想创建可以处理这些组合的函数dir2
:
dir2
这应该列出当前目录中的每个非隐藏文件或文件夹 dir2('path_to_directory')
这应该列出指定目录中的每个未隐藏文件或文件夹 dir2('OnlyDirectories', true)
这应该只列出当前目录中的非隐藏文件夹 dir2('path_to_directory', 'OnlyDirectories', true)
这应该只列出指定目录中的非隐藏文件夹 我目前的版本是:
function list = dir2(varargin)
p = inputParser;
addOptional(p, 'name', '.', @ischar);
addParameter(p, 'OnlyDirectories', false, @islogical);
parse(p, varargin{:});
list = dir(p.Results.name);
if p.Results.OnlyDirectories
dirFlags = [list.isdir];
list = list(dirFlags); % Keeping only directories
end
% Deleting hidden folders from the list
list = list(arrayfun(@(x) ~strcmp(x.name(1),'.'), list));
end
这适用于 1 , 2 和 4 的情况,但对于 3 的情况不起作用。在这种情况下,它给了我错误:
预期参数名称的字符串标量或字符向量,而输入类型为“逻辑”。
我想我可能会遗漏一些关于MATLAB输入解析的小事,但我无法弄清楚是什么。
答案 0 :(得分:2)
你是对的,解析器似乎给出了一些奇怪的结果,相关的问题可能是this one。
对于您当前形式的函数,一种解决方法是添加检查是否给出了2个输入。如果有2个输入,则假设它是您的OnlyDirectories
标志并使用默认的name
值。代码看起来像这样,并传递了所有4个示例用例。
function list = dir2(varargin)
p = inputParser;
addOptional(p, 'name', '.', @ischar);
addParameter(p, 'OnlyDirectories', false, @islogical);
if numel(varargin) == 2
varargin = [{'.'}, varargin];
end
parse(p, varargin{:});
list = dir(p.Results.name);
if p.Results.OnlyDirectories
dirFlags = [list.isdir];
list = list(dirFlags);
end
list = list(arrayfun(@(x) ~strcmp(x.name(1),'.'), list));
end
这个虽然有点hacky,并且有可能给出令人困惑的错误消息。将这两个输入作为名称 - 值对
会更好function list = dir2(varargin)
p = inputParser;
addParameter(p, 'name', '.', @ischar);
addParameter(p, 'OnlyDirectories', false, @islogical);
% ... other code
end
使用:dir2('name', 'C:/Folder/MyStuff/', 'OnlyDirectories', true)
答案 1 :(得分:0)
您的问题是validation function的optional argument不够具体。如你所知,它只是检查它是character array。当您只传递'OnlyDirectories', true
作为第三种情况的参数时,字符串'OnlyDirectories'
会传递您的验证函数,并用作参数'name'
的值。然后您会收到错误,因为剩下的参数是逻辑值而不是参数名称字符串。
使用它作为更严格的验证功能对我有用:
addOptional(p, 'name', '.', @(d) (exist(d, 'dir') == 7));
这使用exist
来检查可选参数是否是有效文件夹。对于第三种情况,字符串'OnlyDirectories'
未传递可选参数'name'
的验证函数,因此使用默认值并传递字符串以检查下一个参数。
修改强>
为了澄清,固有的问题是你想要包含一个字符串的可选参数,参数值对总是以一个参数名开头字符串也是如此。在这种情况下存在一些(可能不可避免的)歧义,inputParser
可以清楚地区分可选字符串与后续参数值对的参数名称的唯一方法是通过您提供的验证功能。如果无法明确区分它们,则应使用required arguments或parameter-value pairs。请注意,如果您的可选参数不是character array or string,那么这不会有问题。
但是,如果你开始使用一个可选参数,我上面提供的一个更具体的验证函数的例子只是一种方法。还有其他选择可能更符合您的喜好。您可以检查可选参数字符串是否不是函数的任何参数名称:
addOptional(p, 'name', '.', @(d) ~ismember(d, {'OnlyDirectories', ...}));
这有一个限制,你永远不能搜索一个输入参数名称的文件夹(无论你选择哪种解决方案,你可能不得不接受歧义)。
还有一个解决方案允许你使用像'path_to_folder/*.csv'
这样的可选参数(即通配符指示符和文件路径):
addOptional(p, 'name', '.', @name_check);
...
function isValid = name_check(d)
try
[dirPath, fileName, fileExt] = fileparts(d);
isValid = ismember('*', d) ... % A wildcard, not allowed in parameter names
|| (isempty(fileExt) && (exist(d, 'dir') == 7)) ... % A folder path
|| (~isempty(fileExt) && (exist(dirPath, 'dir') == 7)); % A file path
catch
isValid = false; % Any failure of the above indicates an invalid argument
end
end