Matlab: Improving a tree traversal code - file

I have the structure that is demonstrated below:
I have a database folder which contains brands. Each brand consists of logo and query.
I want to traverse on all the the files (file_1 to file_n) in all the database and perform some operations on them.
I wrote this code:
d = dir(database);
isub = [d(:).isdir];
brandsFolders = {d(isub).name}';
brandsFolders(ismember(brandsFolders,{'.','..'})) = [];
[numberOfBrands not_used]=size(brandsFolders); %holds the number of the brands
for i=1:numberOfBrands
temp=strcat(database, '\');
currentBrand=strcat(temp, brandsFolders(i));
d = dir(currentBrand{1,1});
isub = [d(:).isdir];
logoAndQuery = {d(isub).name}';
logoAndQuery(ismember(logoAndQuery,{'.','..'})) = [];
logo=strcat(currentBrand, '\', logoAndQuery(1));
files=dir(logo{1,1});
[numberOfFiles not_used]=size(files);
for j=1:numberOfFiles
if strcmp(files(j).name, '..')~=1 && strcmp(files(j).name, '.')~=1
%operations on each files(j).name
end
end
end
The code works fine, it traverse on the desired files.
However, the code is little bit ugly and confusing.
I was wondering if I can do it in another better way?

Traversing through a set of directories goes pretty much as you are doing. However imo, there are some things you can do easier / I would do differently:
brandsFolders = dir(database);
brandsFolders( ~[brandsFolders.isdir] | strcmp({brandsFolders.name},'.') | strcmp({brandsFolders.name},'..')) = [];
for ii=1:numel(brandsFolders)
logoAndQuery = dir(fullfile(database,brandsFolders(ii).name));
logoAndQuery( ~[logoAndQuery.isdir] | strcmp({logoAndQuery.name},'.') | strcmp({logoAndQuery.name},'..')) = [];
logo = fullfile(databasecurrentBrand,brandsFolders(ii).name), logoAndQuery(1).name);
files = dir(logo);
files(strcmp({files.name},'.') | strcmp({files.name},'..'))=[];
for jj=1:numel(files)
%operations on each files(j).name
end
end
(This of course only works if you're sure that logoAndQuery(1) will always be the 'logo' directory.)
or alternatively use a subfunction for the dir-querying:
function dirs = getDirs(strPath)
dirs = dir(strPath);
dirnames = {dirs.name};
dirs ( ~[dirs.isdir] | strcmp(dirnames ,'.') | strcmp(dirnames ,'..')) = [];
end
which gives you already some shorter code and gives the following, in which I also assume there are no directories in the 'logo' directories:
brandsFolders = getDirs(database);
for ii=1:numel(brandsFolders)
logoAndQuery = getDirs(fullfile(database,brandsFolders(ii).name));
logo = fullfile(databasecurrentBrand,brandsFolders(ii).name), logoAndQuery(1).name);
files = dir(logo);
files([files.isdir])=[];
for jj=1:numel(files)
%operations on each files(j).name
end
end

Related

Small Basic: How can I split words in an external text file into a list?

I'm trying to bring in a simple list of 10 words (without commas) on 10 lines and save them as a list or array in Small Basic.
I know I need to loop through all the lines in the file but I can only get it to do it with individual letters.
I've got this far so far
OpenFile = File.ReadContents("example.txt")
For i = 1 To Text.GetLength(OpenFile)
WordList[i] = Text.GetSubText(OpenFile, i, 5)
EndFor
TextWindow.Write(WordList)
I haven't got any further than this and not sure where to go to from here.
YOu could use readline to get all the characters/words/sentence in a line, this is an example, its not complete but it gives the idea of what it is you need,
'SAVE THE PROGRAM FIRST!!!!!
'DO NOT RUN UNTIL YOU DO THAT.
makesaves()
getsaves()
printsaves()
Sub makesaves ' where you make saves. its reusable.
PATH = Program.Directory + "\animals\" ' SAVE THIS IN A FOLDER YOU WILL FIND IN
'ELSE IT WILL SAVE IN A DUMP FOLDER WHICH IS NEARLY IMPOSSIBLE TO FIND
NAME = "Animal"
EXT = ".txt"
filesave["1"] = "Cheetah"
filesave[2] = "horse"
filesave[3] = "dog"
filesave[4] = "cat"
filesave[5] = "mouse"
filesave[6] = "turtle"
filesave[7] ="Bird"
filesave[8] = "snake"
filesave[9] = "snail"
filesave[10] = "Rat"
'makes the saves
File.CreateDirectory(PATH) ' makes the path.
File.WriteContents(PATH+NAME+EXT, filesave)
filesave = "" ' cleans the file so you dont get repeats. e.i. - save dog. read dog, save dog, read dog dog.
'this makes it so you see dog once. its an override.
filesave = File.ReadContents(PATH + NAME + EXT) 'reads the content
endsub
Sub getsaves
filesave = File.ReadContents(PATH+NAME+EXT) ' how this writes is cheetah; horse;
cheetah = filesave[1]
horse = filesave[2]
dog = filesave[3]
cat = filesave[4]
mouse = filesave[5] 'mouse and turtle as different color because they can be used as functions. ignore
turtle = filesave[6]
bird = filesave[7]
snake = filesave[8]
snail = filesave[9]
rat = filesave[10]
EndSub
Sub printsaves
i = 1
While i < 11
TextWindow.WriteLine(filesave[i])
i = i+1
endwhile
endsub
I know I'm probably much too late but in case you're still going (and yes, I'm going to assume that you're not taking an AQA GCSE in Computer Science but instead like to code in Small Basic for fun), but you should be looking at using this code instead as this is much more efficient.
fpath = "\\Downloads\file.txt"
For i = 1 To 10
line[i] = File.ReadLine(fpath, i)
EndFor
For i = 1 To 10
TextWindow.WriteLine("Line " + i + " contains: " + line[i])
EndFor
(You'll need to change the fpath variable to wherever your file is). This then also prints out the array just to check but for your task you'll need to get rid of that.

How to exclude the zeros that results from file's self comparisons and keep all the values other than that in the final array

i want to exclude the zeros that results from file's self comparisons and keep all the values other than that in the final array. what i am doing is using ~= for file comparison but not succeeded yet. Also tried strcmp. my code is as follows.
dirName= 'C:\Users\PCPC\U1'; %# folder path
files = dir( fullfile(dirName,'*.HWR') ); %# list all *.HWR files
files = {files.name}; %'# file names
supfinal = [];
final = [];
dist = [];
for i=1:length(files)
fname = fullfile(dirName,files{i});
c = dlmread(fname, '', 0,0);
c1=c(:,1);
for j=1:length(files)
fname = fullfile(dirName,files{j});
d = dlmread(fname, '', 0,0);
d1=d(:,1);
**if (j ~= i)**
dist = dtw(c1,d1); %# SOme Calculation
final = [final; dist];
end
end
**supfinal = [supfinal; final];**
end
i want from my code to give me results other than self comparison in the supfinal array. what's wrong i am doing. How to correct?

How to use arrays created by loop? Matlab

The code I'm using imports data from multiple files and saves them into an array of cells, the code is as follows:
[FileName,PathName,FilterIndex] = uigetfile('*.txt*','MultiSelect','on');
numfiles = size(FileName,2);
FileData= cell(1,numfiles);
for ii = 1:numfiles
FileName{ii};
A=[];
entirefile =fullfile(PathName,FileName{ii});
fid = fopen(entirefile);
tline = fgets(fid);
while ischar(tline)
parts = textscan(tline, '%f;');
if numel(parts{1}) > 0
A = [ A ; parts{:}' ];
end
tline = fgets(fid);
end
fclose(fid);
FileData{ii} = A;
A = FileData{ii};
X = A(:,1);
Y = A(:,5);
DataToUse = [X,Y];
end
Now my issue is I want to use the first DataToUse created by the loop, which will be data from the first file, seperatley to the other files but I can not issolate it. I have tried DataToUse(1), DataToUse(1,1) and DataToUse(:,[1,2]) but none are working for me. An example of the type of data would be:
DataToUse=
0.0762 0.0271
0.0763 0.2671
0.0764 0.4079
0.0765 0.0510
0.0766 0.0087
0.0767 0.0099
0.0768 0.0067
0.0769 0.0047
0.0770 0.0047
0.0771 0.0349
0.0772 0.2094
0.0773 0.2740
0.0774 0.0294
0.0775 0.0100
0.0776 0.0159
I have different numbers of this kind of data depending on how many files are selected but I would like to only use the first initially and use the others later. Anybody know how I can go about doing this? Many thanks in advance
The solution is to use cell arrays, like so:
DataToUse{ii} = [X, Y]
To get the desired output put this after your for-loop:
firstLoopXY = DataToUse{1}
Enjoy!

Convert MyList(,) of Object to String array with LINQ

I have a little problem with the performance of one of my applications, basically:
An external system gives me a big structure as an Object(,).
This structure only has an column per row.
MyData(0,0) = 'COL1-ROW1 | COL2-ROW1 | COL3-ROW1'
MyData(1,0) = 'COL1-ROW2 | COL2-ROW2 | COL3-ROW2'
MyData(2,0) = 'COL1-ROW3 | COL2-ROW3 | COL3-ROW3'
MyData(3,0) = 'COL1-ROW4 | COL2-ROW4 | COL3-ROW4'
MyData(0,1) ' Doesn't exists.
There are some method in LINQ to convert this structure to an one dimensional array of strings?
It would be awesome if you could divide by columns, given a specific character.
Something like this:
NewData(0,0) = COL1-ROW1
NewData(0,1) = COL2-ROW1
NewData(0,2) = COL3-ROW1
NewData(1,0) = COL1-ROW2
...
NewData(3,2) = COL3-ROW3
Seems I found the answer from myself; here my solution:
Dim vMyData(1000, 0) As Object
For x = 0 To 1000
vMyData(x, 0) = String.Format("ROW{0}COL1|ROW{0}COL2|ROW{0}COL3|ROW{0}COL4", x)
Next
Dim vQuery = From TempResult In vMyData
Select Value = TempResult.ToString.Split("|")
Dim vMyNewArray As New ArrayList(vQuery.ToArray)
Now; exists some method to trim each value of the Split("|")?
[UPDATE TO THE PREVIOUS QUESTION]:
From TempResult In vMyData Select Value = Array.ConvertAll(TempResult.ToString.Split("|"), Function(vVal) vVal.ToString.Trim)

Function that outputs multiple datasets

I am working in MATLAB.
I have a function that loops through all the files in a directory, runs them and concatenates their dataset outputs into a single dataset.
Is there a way that I can alter my function so that it outputs all the individual datasets as well as the unified one?
Below, the array named "FileInfo" has 3 columns. The first has the file name, and the second and third columns are the inputs
function [AllFunOutputs] = RunAllFuns(FileInfo)
fileDir = dir('C:\MATLAB\Funs'); % get all file names in directory 'Funs'
files = {fileDir.name};
funNames = strrep(files, '.m', ''); % strip the '.m' suffix from all files
funNames(:,1:2) = [];
funNames = transpose(funNames);
k = 1; % below, match the function name with its argument
for i=1:length(FileInfo)
if strcmp(FileInfo(i,1),funNames(k,1))
funNames(k,3) = FileInfo(i,2);
k = k+1;
end
end
% create function handles
fh_array = cellfun(#str2func,{funNames{:,1}},'UniformOutput', false);
X = []; % below, concatenate all output datasets into a single dataset
for i=1:size((funNames),1)
X=[fh_array{i}(funNames(i,2),(funNames(i,3)))];
X = X+1;
end
so..... why doesn't this work to give me the output dataset of all the functions?
nFcns = numel(fh_array); % number of functions to evaluate
for i=1:size(nFcns)
[allresults] = feval(#(i)funNames(i,2),funNames(i,3));
end
Thank you so much for your help and time!

Resources