Renaming a structure in MATLAB using an existing string - string

I have a structure in MATLAB called dat. I want to rename dat as an existing string.
Existing_str='NewName'
$(Existing_str)=dat
This fails as I don't think MATLAB lets me use the dollar sign in this way. The code below creates a copy of dat literally called Existing_str and destroys the Existing_str in the process.
Existing_str=dat
While the code below generates a collosal empty structure which clearly is not a copy!
eval(Existing_str)=dat
In the task I am actually trying to perform I don't know the name of the existing_str in advance so that is not a solution.

You were almost there with your `eval'. What you want is:
eval([Existing_str '=dat;']);
This works because you're composing a string inside your square brackets. If you just looked at the resulting string, it would look like NewName=dat; The eval command simply tells Matlab to evaluate the string as if you typed it into the command line.

You can use dynamic field naming (Bas's suggestion), and avoid eval:
For example, if you have just loaded a structure dat from a file 'somefile.ext' with some custom parsing function:
filename = 'somefile.ext'; % presume you actually have a list of files from dir or ls
dat = yourfunction(filename);
[~, name, ~] = fileparts(filename);
alldat.(name)=dat;
This is equivalent to:
alldat.somefile = dat;
Except that we've just automatically taken the name from the filename (in this case just by stripping off the path/extension, but you could do other things depending on the pattern of the filename).
The bonus of this is that you can then, say, with a structure that has fields alldat.file1, alldata.file2, alldat.file3, all of which have a subfield, say, size do things like this:
names = fieldnames(alldat)
for n = 1:length(names)
alldat.(names{n}).mean = mean(alldata.(names{n}).size);
end
Every sub-structure now has a field, mean, which contains the mean of the data. If you had a bunch of different named structures you would need to eval everything you wanted to do to them collectively, and the code becomes difficult to read and maintain.
The other option is a cell array. Here's an easy trick:
dat = % whatever you do to make this structure
alldat{end+1} = dat;
This just appends the new dat onto the end of an existing cell array. {end+1} ensures it doesn't overwrite existing data.

Related

In IDL, how can I access a variable given its name?

I would like to convert a string to a variablename, so it can be read as a already restored variable.
So, I look through a file, and look at all the files. I use RESTORE to use the file in IDL, restore names this object as something slightly different. It names it as an object which we'll call map_1 (in the code it's called filerestore_name). This is related to the file name and I can recreate this variable name - however, its saved as a string.
Now, I pass this onto the make_cool_video procedure. However, althoughthis string now is exactly the same as the varialbe name, its still a string!.
Thus, as its a string, the procedure can't work.
filenames=FILE_SEARCH('rxrt*')
filenames_withoutextension = STREGEX(filenames,'rxrt_[0-9]+[a-zA-Z_]+',/EXTRACT,/FOLD_CASE)
restore, '/home/tomi/Documents/actualwork/'+filenames_withoutextension(18)+'.idl_sav',
filerestore_name = STRJOIN(STRSPLIT(filenameswithout(18),'_[0-9]+',/EXTRACT,/REGEX),'')
PRINT, filerestorename
make_cool_video, EXECUTE(filerestore_name),filename=filerestorenames, outdir='/path/to.file/'
retall
What I tried: using the RESTORE function and the associated RESTORED_OBJECTS to store pointers in an array, and then referring to the array. But I couldn't get the restore function to form an array.
Using EXECUTE(filerestore_name) however, this doesn't convert it as I was expecting.
I would recommend using SCOPE_VARFETCH() instead (it isn't as limited as EXECUTE() and is probably more efficient). You can do something like:
make_cool_video, (SCOPE_VARFETCH(filerestore_name)), filename=filerestorenames, outdir='/path/to.file/'
I wrote this, then immediately thought of the answer.
So,
Convert everything to a string:
string1 = "makecooljes, "+ filerestore_name, outdir='file/to/path/'"
result= EXECUTE(string1)

need guidance with basic function creation in MATLAB

I have to write a MATLAB function with the following description:
function counts = letterStatistics(filename, allowedChar, N)
This function is supposed to open a text file specified by filename and read its entire contents. The contents will be parsed such that any character that isn’t in allowedChar is removed. Finally it will return a count of all N-symbol combinations in the parsed text. This function should be stored in a file name “letterStatistics.m” and I made a list of some commands and things of how the function should be organized according to my professors' lecture notes:
Begin the function by setting the default value of N to 1 in case:
a. The user specifies a 0 or negative value of N.
b. The user doesn’t pass the argument N into the function, i.e., counts = letterStatistics(filename, allowedChar)
Using the fopen function, open the file filename for reading in text mode.
Using the function fscanf, read in all the contents of the opened file into a string variable.
I know there exists a MATLAB function to turn all letters in a string to lower case. Since my analysis will disregard case, I have to use this function on the string of text.
Parse this string variable as follows (use logical indexing or regular expressions – do not use for loops):
a. We want to remove all newline characters without this occurring:
e.g.
In my younger and more vulnerable years my father gave me some advice that I've been turning over in my mind ever since.
In my younger and more vulnerableyears my father gave me some advicethat I’ve been turning over in my mindever since.
Replace all newline characters (special character \n) with a single space: ' '.
b. We will treat hyphenated words as two separate words, hence do the same for hyphens '-'.
c. Remove any character that is not in allowedChar. Hint: use regexprep with an empty string '' as an argument for replace.
d. Any sequence of two or more blank spaces should be replaced by a single blank space.
Use the provided permsRep function, to create a matrix of all possible N-symbol combinations of the symbols in allowedChar.
Using the strfind function, count all the N-symbol combinations in the parsed text into an array counts. Do not loop through each character in your parsed text as you would in a C program.
Close the opened file using fclose.
HERE IS MY QUESTION: so as you can see i have made this list of what the function is, what it should do, and using which commands (fclose etc.). the trouble is that I'm aware that closing the file involves use of 'fclose' but other than that I'm not sure how to execute #8. Same goes for the whole function creation. I have a vague idea of how to create a function using what commands but I'm unable to produce the actual code.. how should I begin? Any guidance/hints would seriously be appreciated because I'm having programmers' block and am unable to start!
I think that you are new to matlab, so the documentation may be complicated. The root of the problem is the basic understanding of file I/O (input/output) I guess. So the thing is that when you open the file using fopen, matlab returns a pointer to that file, which is generally called a file ID. When you call fclose you want matlab to understand that you want to close that file. So what you have to do is to use fclose with the correct file ID.
fid = open('test.txt');
fprintf(fid,'This is a test.\n');
fclose(fid);
fid = 0; % Optional, this will make it clear that the file is not open,
% but it is not necessary since matlab will send a not open message anyway
Regarding the function creation the syntax is something like this:
function out = myFcn(x,y)
z = x*y;
fprintf('z=%.0f\n',z); % Print value of z in the command window
out = z>0;
This is a function that checks if two numbers are positive and returns true they are. If not it returns false. This may not be the best way to do this test, but it works as example I guess.
Please comment if this is not what you want to know.

How to save strings in matrixes in matlab

I want to have a matrix/cell, that has strings inside that I can access and use later as strings.
For instance, I have one variable (MyVar) and one cell (site) with names inside:
MyVar=-9999;
site={'New_York'; 'Lisbon'; 'Sydney'};
Then I want to do something like:
SitePosition=strcat(site{1},'_101'}
and then do this
save(sprintf('SitePosition%d',MyVar),);
This doesn't work at all! Is there a way to have strings in a matrix and access them in order to keep working with them if they were a string?
This:
MyVar=-9999; site={'New_York'; 'Lisbon'; 'Sydney'};
SitePosition = strcat(site{1},'_101');
save(sprintf('SitePosition%d',MyVar));
Works fine and yields SitePosition-9999.mat, note the syntax changes in lines 2 and 3.
Is there something else you're expecting?
EDIT: Based on your comment
Check out the documentation for save regarding saving specific variables
New example:
MyVar=-9999;
site={'New_York'; 'Lisbon'; 'Sydney'};
SitePosition = strcat(site{1},'_101');
save(SitePosition,'MyVar');
Creates New_York_101.mat with only the variable MyVar in it.

Unicode name from Char

I'm looking for a function that takes a Char as input and gives the unicode name of that code point (::Char->String), but I couldn't find any results on Hoogle. I assume that there is no builtin (If there is, please let me know) and so I wonder what's the best way to write this function and its inverse (::String->Maybe Char).
I know you'd have to read UnicodeData.txt or a similar document, but I don't know what the best/fastest function would be.
The unicode-names package contains the function
getCharacterName :: Char -> String
First of all, thanks to #TwanVanLaarhoven who provided an excellent answer. I did however need a function that did the reverse of getCharacterName.
What I originally wanted was a function that would read the file and not have it hard-coded, but I eventually realized that that would require unsafe IO operations.
What I decided to do was to copy UnicodeData.txt into notepad++ and use the following regex replacements:
write module UnicodeNames (characterToName,nameToCharacter) where
paste UnicodeData.txt
replace this: ^([\dA-F]+);([^<;>]+).*$|^([\dA-F]+);(?:[^;]*;){9}([^<;>]+).*$
with this: characterToName '\\x$1$3' = "$2$4"
append characterToName _ = ""
paste again
replace this (again): ^([\dA-F]+);([^<;>]+).*$|^([\dA-F]+);(?:[^;]*;){9}([^<;>]+).*$
with this: nameToCharacter "$2$4" = Just '\\x$1$3'
append nameToCharacter _ = Nothing
replace ^.*<.*$ with nothing to remove extra lines.
The file will be incredibly long and take forever to compile :-) In addition to having an inverse function, this method has the advantage of providing more names than the unicode-names package by using unicode 1.0 names as well. The two functions in this file rely on pattern matching to act as a dictionary from char to string and vice-versa. I would put my solution on PasteBin or somewhere else if it didn't use a ton of memory.

How to return dynamically created vectors to the workspace?

Hello I'm trying to write a function which reads a certain type of spreadsheet and creates vectors dynamically from it's data then returns said vectors to the workspace.
My xlcs is structured by rows, in the first row there is a string which should become the name of the vector and the rest of the rows contain the numbers which make up the vector.
Here is my code:
function [ B ] = read_excel(filename)
%read_excel a function to read time series data from spreadsheet
% I get the contents of the first cell to know what to name the vector
[nr, name]=xlsread(filename, 'sheet1','A2:A2');
% Transform it to a string
name_str = char(name);
% Create a filename from it
varname=genvarname(name_str);
% Get the numbers which will make up the vector
A=xlsread(filename,'B2:CT2');
% Create the vector with the corect name and data
eval([varname '= A;']);
end
As far as I can tell the vector is created corectly, but I have no ideea how to return it to the workspace.
Preferably the solution should be able to return a indeterminate nr of vectors as this is just a prototype and I want the function to return a nr of vectors of the user's choice at once.
To be more precise, the vector varname is created I can use it in the script, if I add:
eval(['plot(',varname,')'])
it will plot the vector, but for my purposes I need the vector varname to be returned to the workspace to persist after the script is run.
I think you're looking for evalin:
evalin('base', [varname '= B;']);
(which will not work quite right as-is; but please read on)
However, I strongly advise against using it.
It is often a lot less error-prone, usually considered good practice and in fact very common to have predictable outcomes of functions.
From all sorts of perspectives it is very undesirable to have a function that manipulates data beyond its own scope (i.e., in another workspace than its own), let alone assign unpredictable data to unpredictable variable names. This is unnecessarily hard to debug, maintain, and is not very portible. Also, using this function inside other functions does not what someone who doesn't know your function would think it does.
Why not use smoething like a structure:
function B = read_excel(filename)
...
B.data = xlsread(filename,'B2:CT2');
B.name = genvarname(name_str);
end
Then you always have the same name as output (B) which contains the same data (B.data) and whose name you can also use to reference other things dynamically (i.e., A.(B.name)).
Because this is a function, you need to pass the variables you create to an output variable. I suggest you do it through a struct as you don't know how many variables you want to output upfront. So change the eval line to this:
% Create the vector with the correct name and data
eval(['B.' varname '= A;']);
Now you should have a struct called B that persists in the workspace after running the function with field names equal to your dynamically created variable names. Say for example one varname is X, you can now access it in your workspace as B.X.
But you should think very carefully about this code design, dynamically creating variables names is very unlikely to be the best way to go.
An alternative to evalin is the function assignin. It is less powerfull than evalin, but does exacty what you want - assign a variable in a workspace.
Usage:
assignin('base', 'var', val)

Resources