动态创建for循环matlab

时间:2014-09-12 16:12:39

标签: matlab

我给了一个带有变量名称L1dirs,L2dirs等的结构,一直到用户想要的多个级别。每个Lxdirs都包含一个要创建的目录名称的单元格数组。

最终结果应该是创建一组嵌套目录,其中每个1级目录包含所有2级目录,所有2级目录包含所有3级目录,等等。如何动态创建此层次结构?

从下面的代码中,我已经通过try-catch语句找到了用户指定的级别数。

现在我们知道用户指定了多少级别,我们如何生成所有唯一文件路径组合的列表?最终结果应该是m个路径的列单元数组,其中错误的L1目录数乘以L2目录数乘以Lx目录数的倍数。

MATLAB可以这样做吗?我试图通过创建一个动态创建的字符串宏来使用eval(),但是当尝试动态嵌套for循环时,eval不喜欢使用end语句。还有另一种方式吗?

以下是我目前所拥有的一段代码示例:

主要代码

userinputs.L1dirs = {'Level 1 Dir 1';
  'Level 1 Dir 2';
  'Level 1 Dir 3'};
userinputs.L2dirs = {'Level 2 Dir 1';
  'Level 2 Dir 2';
  'Level 2 Dir 3'};
userinputs.L3dirs = {'Level 3 Dir 1';
  'Level 3 Dir 2';
  'level 3 Dir 3'};

userinputs.top_level_dir = strcat(pwd,'\Results\');

pathlist1 = check_results_dirs(userinputs)


userinputs.L4dirs = {'Level 4 Dir 1';
             'Level 4 Dir 2'};
userinputs.top_level_dir = strcat(pwd,'\Results 2\');
pathlist2 = check_results_dirs(userinputs)

支持功能

function pathlist = check_results_dirs(inputdata)
%{
This function checks if the file directory exists in the top level
directory as specified by the inputs structure.  If the directory already
exists, then it checks whether these files are to be overwritten or not.  

This function dynamically checks how many levels of directories the user
specified.  

Inputs
inputdata - structure containing the following variable names
inputdata.LXdirs - X is an integer value.  Variable(s) contain cell
arrays of directory names

inputdata.top_level_dir - top level destination directory to
create this file structure.  If this folder does not exist, it will be
created.
%}

%check if top level directory exists
if ~exist(inputdata.top_level_dir,'file')
    mkdir(inputdata.top_level_dir);
end

%determine how many directory levels there are as determined by the user
numDirLevels = 1;
numDirsPerLevel = [];
moreDirsFlag = 1;
while moreDirsFlag
try
    eval(sprintf('temp = inputdata.L%idirs;',numDirLevels));
    numDirsPerLevel = [numDirsPerLevel; length(temp)];
    numDirLevels = numDirLevels + 1;
catch err
    if strcmp(err.identifier,'MATLAB:nonExistentField')
        %no more directory levels
        numDirLevels = numDirLevels - 1;
        moreDirsFlag = 0;
    else
        rethrow(err);
    end
end
end

numUniqueDirs = prod(numDirsPerLevel);

%Generate Path list

beginstr = '';
midstr = 'pathlist{numUniqueDirs} = strcat(';
endstr = '';
for ii = 1:numDirsPerLevel
    beginstr = strcat(beginstr,sprintf('for x%i=1:numDirsPerLevel(%i) ',ii,ii));
    midstr = strcat(midstr,sprintf('inputdata.L%idirs(x%i),''\\'',',ii,ii)); 
    endstr = strcat(' end ',endstr);
end
midstr = strcat(midstr,''''');');
evalstr = ' numUniqueDirs = numUniqueDirs+1;'
midstr = strcat(midstr,evalstr);

evalstr = 'numUniqueDirs = 1; '
beginstr = strcat(evalstr,beginstr);


eval(strcat(beginstr,midstr,endstr));  %error is thrown here due to an illegal 
%use of 'end'.  Can I not 
%use for loops using eval?

%debug statements
disp(beginstr)
disp(midstr)
disp(endstr)

end

注意在主代码中如何调用两次函数。一旦调用它来制作三级目录,另一个调用就是制作四级目录。输出路径列表应该包含numL1dirs次数numL2dirs次.... times numLxdirs所以对于第一个例子,它应该创建27个不同的目录,这样每个1级dir包含所有3个2级目录,每个2级dir包含所有3个3级目录。对于第二个示例,pathlist应包含54个唯一目录路径。

1 个答案:

答案 0 :(得分:1)

你挣扎这么多的原因可能是你对eval的依恋。你需要真正限制它的使用到一个严格的最低限度...理想情况下永远不会。我可以看出为什么你认为你不得不诉诸它(你的动态字段/变量名称),但幸运的是Matlab给了我们一些工具来克服它。

您应该好好了解Matlab的Dynamic field names功能。考虑到你的编程风格,这可能会很有用,并尽可能多地使用它来避免使用邪恶的eval

一旦你使用它。执行递归调用以生成表示要生成的文件夹的所有路径的字符串列表,然后mkdir它们就完成了。

function pathList = Generate_PathList(userinputs)

%% // check if top level directory exists
if ~exist(userinputs.top_level_dir,'dir')
    mkdir(userinputs.top_level_dir);
end

%% // determine how many directory levels there are
fnames = fieldnames(userinputs) ;
maxDirLevel = 1 ;
for iField = 1:numel(fnames)
    lvlDir = sscanf(fnames{iField},'L%idirs') ;
    if lvlDir > maxDirLevel
        maxDirLevel = lvlDir ;
    end
end

%% // Generate string list
pathList = { userinputs.top_level_dir } ;
for iLvl = 1:maxDirLevel % // loop on all directory level
    dirLevelName = ['L' num2str(iLvl) 'dirs'] ;
    pathList = addPathToList( pathList , userinputs.(dirLevelName) ) ;     
end

%% // Generate the directories
for iDir = 1:numel(pathList)
    mkdir( pathList{iDir} ) ;
end

%% // Helper function called recursively
function pathListOut = addPathToList( pathList , dirNames )
    nTop = numel(pathList) ;
    nLow = numel(dirNames) ;
    pathListOut = cell( nTop*nLow , 1 ) ;
    iPath = 0 ;
    for iTopDir = 1:nTop
        for iLowDir = 1:nLow
            iPath = iPath + 1 ;
            pathListOut{iPath} = [pathList{iTopDir} '\' dirNames{iLowDir}] ;
        end
    end

您可以像调用初始函数一样调用此函数:

userinputs.top_level_dir = strcat(pwd,'\Results');
pathList = Generate_PathList(userinputs)

userinputs.L4dirs = {'Level 4 Dir 1';
             'Level 4 Dir 2'};
userinputs.top_level_dir = strcat(pwd,'\Results 2');
pathList = Generate_PathList(userinputs)

将创建您的27个和54个独特文件夹。

请注意,我删除了顶级文件夹定义中的最后一个'\'(与稍后使用的文件夹路径生成一致...)