2014-09-12 139 views
0

我得到一個結構變量名稱L1dirs,L2dirs ...等等一直到用戶想要的任何級別。每個Lxdirs包含要創建的目錄名稱的單元數組。動態創建for循環matlab

最終的結果應該是一組嵌套目錄,其中每個一級目錄包含所有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級目錄包含全部三個二級目錄,每個二級目錄包含所有三個三級目錄。對於第二個示例,pathlist應該包含54個唯一的目錄路徑。

回答

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分別獨特的文件夾。

請注意,我刪除了頂級文件夾定義中的最後一個'\'(與以後使用的文件夾路徑生成一致...)