Matlab evaluating a string containing operations - string

I have a first structure like:
struct1.Vx.Value=10;
struct1.Vy.Value=2;
In a 2nd structure, I write operations as strings:
struct2.param1.map='sqrt(Vx^2+Vy^2)';
struct2.param2.map='Vx+Vy';
What is the most efficient way to set:
struct2.param1.value= [sqrt(10^2+2^2)=10.198]
struct2.param2.value= [10+2=12]
I found a solution using assignin and fieldnames on struct1 to create variables Vx=10 and Vy=2
then, I use eval() on struct2 to perform the operations.
Ok, it works but I don't like this solution reading what is said on eval()...
Is there a more efficient way to do what I want?
Thanks!

I manage to find a good solution, formating my data differently:
s.Vx = 10;
s.Vy = 2;
Map1 = 'sqrt( s.Vx^2+ s.Vy^2)';
FunctionMap1 = str2func( [#(s) Map1] );
And then I can evaluate my function handle simply with:
Value = FunctionMap1(s)

Related

Populating a std::vector map using the operator[]?

Am I overcomplicating this? Since I recently learned that with std::vector you can use the [] operator and it will add the entry if missing.
I have something a little more detailed:
using WeekendFutureItemHistMap = std::map<CString, std::vector<COleDateTime>>;
using WeekendFutureHistMap = std::map<WeekendHistAssign, WeekendFutureItemHistMap>;
WeekendHistAssign is just an enum class.
In my function I am populating it this way:
if (m_mapScheduleFutureHist[eHistAssign].find(strName) != m_mapScheduleFutureHist[eHistAssign].end())
m_mapScheduleFutureHist[eHistAssign][strName].push_back(datAssign);
else
{
m_mapScheduleFutureHist[eHistAssign].emplace(strName, std::vector<COleDateTime>{datAssign});
}
According to the std::vector operator[] it states:
Returns a reference to the element at specified location pos. No bounds checking is performed.
As a result it seemed the right thing to do is test for the existing first as done.
Did I overcomplicate it?
std::vector<int> v;
v.resize(100);
v[0]=1;
v[1]=10;
...

Matlab - dynamically produce string for anonymous function

I am trying to produce the argument string for an anonymous function based on the number of input arguments without using for loops. For example, if N=3, then I want a string that reads
#(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))
I tried using repmat('ax',1,N) but I cannot figure out how to interleave the (i) index.
Any ideas?
Aside: Great answers so far, the above problem has been solved. To provide some intuition for those who are wondering why I want to do this: I need to construct a very large matrix anonymous function (a Jacobian) on the order of 3000x3000. I initially used the Matlab operations jacobian and matlabFunction to construct the anonymous function; however, this was quite slow. Instead, since the closed form of the derivative was quite simple, I decided to form the anonymous function directly. This was done by forming the symbolic Jacobian matrix, J, then appending it to the above #() string by using char(J{:})' and using eval to form the final anonymous function. This may not be the most elegant solution but I find it runs much faster than the jacobian/matlabFunction combination, especially for large N (additionally the structure of the new approach allows for the evaluation to be done in parallel).
EDIT: Just for completeness, the correct form of the argument string for the anonymous function should read
#(ax1,ax2,ax3,ay1,ay2,ay3)
to avoid a syntax error associated with indexing.
I suggest the following:
N = 3;
argumentString = [repmat('ax(%i),',1,N),repmat('ay(%i),',1,N)];
functionString = sprintf(['#(',argumentString(1:end-1),')'], 1:N, 1:N)
First, you create input masks for sprintf (e.g. 'ax(%i)'), which you then fill in with the appropriate numbers to create the function string.
Note: the syntax #(ax(1),...) will not actually work. More likely, you want to use either #()someFunction(ax(1),...), or you are trying to pass multiple input arguments to an existing function, in which case storing the inputs in a cell array and calling the function as fun(axCell{:}) would work.
A solution would be to use arrayfun:
sx = strjoin(arrayfun(#(x) ['ax(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
sy = strjoin(arrayfun(#(x) ['ay(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
s = ['#(' sx ',' sy ')'];
contains
'#(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))'
Best,
Try this:
N = 3;
sx = strcat('ax(', arrayfun(#num2str, 1:N, 'uniformoutput', 0), '),');
sy = strcat('ay(', arrayfun(#num2str, 1:N, 'uniformoutput', 0), '),');
str = [sx{:} sy{:}];
str = ['#(' str(1:end-1) ')']

How to convert a string into a variable name in MATLAB? [duplicate]

Let's assume that I want to create 10 variables which would look like this:
x1 = 1;
x2 = 2;
x3 = 3;
x4 = 4;
.
.
xi = i;
This is a simplified version of what I'm intending to do. Basically I just want so save code lines by creating these variables in an automated way. Is there the possibility to construct a variable name in Matlab? The pattern in my example would be ["x", num2str(i)]. But I cant find a way to create a variable with that name.
You can do it with eval but you really should not
eval(['x', num2str(i), ' = ', num2str(i)]); %//Not recommended
Rather use a cell array:
x{i} = i
I also strongly advise using a cell array or a struct for such cases. I think it will even give you some performance boost.
If you really need to do so Dan told how to. But I would also like to point to the genvarname function. It will make sure your string is a valid variable name.
EDIT: genvarname is part of core matlab and not of the statistics toolbox
for k=1:10
assignin('base', ['x' num2str(k)], k)
end
Although it is long overdue, i justed wanted to add another answer.
the function genvarname is exactly for these cases
and if you use it with a tmp structure array you do not need the eval cmd
the example 4 from this link is how to do it http://www.mathworks.co.uk/help/matlab/ref/genvarname.html
for k = 1:5
t = clock;
pause(uint8(rand * 10));
v = genvarname('time_elapsed', who);
eval([v ' = etime(clock,t)'])
end
all the best
eyal
If anyone else is interested, the correct syntax from Dan's answer would be:
eval(['x', num2str(i), ' = ', num2str(i)]);
My question already contained the wrong syntax, so it's my fault.
I needed something like this since you cannot reference structs (or cell arrays I presume) from workspace in Simulink blocks if you want to be able to change them during the simulation.
Anyway, for me this worked best
assignin('base',['string' 'parts'],values);

How to convert a number to string in coffeescript?

Given a number
n = 42
What is the best way to convert it into a string?
s = String(n)
or
s = ''+n
or any better suggestion?
String interpolation might be the most natural approach in CoffeeScript:
s = "#{n}" # Just `'' + n` in disguise.
That might leave people wondering what you're doing though.
I think the best way would be:
(10).toString()
// or
n = 11;
n.toString()
Edited to fix syntax error. 10.toString() works in the CoffeeScript simulator but it's better to be safe.
There is no solution that is more "natural" than the other. Both are explicit and the reader will understand what it does right away in both cases.
Concerning performance, from this test, the fastest is :
s = '' + n
The other method, String(n), is slower.

Best way to build object from delimited string (hopefully not looped case)

this question feels like it would have been asked already, but I've not found anything so here goes...
I have constructor which is handed a string which is delimited. From that string I need to populate an object's instance variables. I can easily split the string by the delimited to give me an array of strings. I know I can simply iterate through the array and set my instance variables using ifs or a switch/case statement based on the current array index - however that just feels a bit nasty. Pseudo code:
String[] tokens = <from generic string tokenizer>;
for (int i = 0;i < tokens.length;i++) {
switch(i) {
case(0): instanceVariableA = tokens[i];
case(1): instanceVarliableB = tokens[i];
...
}
}
Does anyone have any ideas of how I do this better/nicer?
For what it's worth, I'm working in Java, but I guess this is language independant.
Uhm... "nasty" is in the way the constructor handles the parameters. If you can't change that then your code snippet is as good as it may be.
You could get rid of the for loop, though...
instanceVariableA = tokens[0];
instanceVariableB = tokens[1];
and then introduce constants (for readibilty):
instanceVariableA = tokens[VARIABLE_A_INDEX];
instanceVariableB = tokens[VARIABLE_B_INDEX];
NOTE: if you could change the string parameter syntax you could introduce a simple parser and, with a little bit of reflection, handle this thing in a slightly more elegant way:
String inputString = "instanceVariableA=some_stuff|instanceVariableB=some other stuff";
String[] tokens = inputString.split("|");
for (String token : tokens)
{
String[] elements = token.split("=");
String propertyName = tokens[0];
String propertyValue = tokens[1];
invokeSetter(this, propertyName, propertyValue); // TODO write method
}
Could you not use a "for-each" loop to eliminate much of the clutter?
I really think the way you are doing it is fine, and Manrico makes a good suggestion about using constants as well.
Another method would be to create a HashMap with integer keys and string values where the key is the index and the value is the name of the property. You could then use a simple loop and some reflection to set the properties. The reflection part might make this a bit slow, but in another language (say, PHP for example) this would be much cleaner.
just an untested idea,
keep the original token...
String[] tokens = <from generic string tokenizer>;
then create
int instanceVariableA = 0;
int instanceVariableB = 1;
if you need to use it, then just
tokens[instanceVariableA];
hence no more loops, no more VARIABLE_A_INDEX...
maybe JSON might help?
Python-specific solution:
Let's say params = ["instanceVariableA", "instanceVariableB"]. Then:
self.__dict__.update(dict(zip(params, tokens)))
should work; that's roughly equivalent to
for k,v in zip(params, tokens):
setAttr(self, k, v)
depending on the presence/absence of accessors.
In a non-dynamic language, you could accomplish the same effect building a mapping from strings to references/accessors of some kind.
(Also beware that zip stops when either list runs out.)

Resources