What are some good ways to emulate cascading indexing in MATLAB? [duplicate] - matlab

This question already has answers here:
How can I index a MATLAB array returned by a function without first assigning it to a local variable?
(9 answers)
Closed 8 years ago.
E.g. I would like to do things such as:
A=4:20;
find(A>5)(2) % want to access the 2nd element of the index array returned by find

Yes, this comes up fairly frequently in different contexts, and the one-line answer is subsref. For your case, it is this:
subsref(find(A>5),struct('type','()','subs',{{2}}))
A much cleaner solution uses an undocumented builtin:
builtin('_paren',find(A>5),2)
As an alternative to ugly syntax or undocumented functionality, you could define a small function like the following,
function outarray = nextind(inarray,inds)
outarray = inarray(inds);
Or an inline function:
nextind = #(v,ii) v(ii);
And call it like nextind(find(A>5),2). This is cleaner than subsref and good if you are doing linear indexing (not subscripts).

Related

How to index a temporary matrix? [duplicate]

This question already has answers here:
How can I index a MATLAB array returned by a function without first assigning it to a local variable?
(9 answers)
Closed 6 years ago.
When I want to access a specific element of a matrix, I use indexing with parentheses:
m = calc_stuff(...);
x = m(index1, index2);
However, I often want to do that in one line of code, like this:
x = calc_stuff(...)(index1, index2);
How can I express it?
A specific example:
m = cumsum(rand(10,4));
x = m(10, 1);
The above script calculates some sums of random variables, and then I take one example value out of the result matrix.
How could I write it as one line? The following doesn't work:
x = cumsum(rand(10,4))(10, 1);
Error: ()-indexing must appear last in an index expression.
Here, I want a general syntax, which is applicable for any calculation, not necessarily involving random variables.
You may want to check out the "Functional Programming Constructs" on the FileExchange).
Especially the file paren.m does what you need. So you would write
x = paren( cumsum(rand(10,4)), 10, 1 );
Perhaps not as elegant as the direct "()"notation, but that is not supported in MATLAB in the way you would like to use it.

How to create serially numbered variables in workspace? [duplicate]

This question already has answers here:
Dynamic variables matlab
(2 answers)
Closed 8 years ago.
I was wondering how I can use a for loop to create multiple matrix when given a certain number.
Such as If 3 was given I would need three matricies called: C1, C2 and C3.
k = 3
for i = 1:K
C... = [ ]
end
Not sure how to implement this.
The first thing coming in mind is the eval function mentioned by Dennis Jaheruddin, and yes, it is bad practice. So does the documentation say:
Why Avoid the eval Function?
Although the eval function is very powerful and flexible, it not
always the best solution to a programming problem. Code that calls
eval is often less efficient and more difficult to read and debug than
code that uses other functions or language constructs. For example:
MATLAB® compiles code the first time you run it to enhance performance for future runs. However, because code in an eval
statement can change at run time, it is not compiled.
Code within an eval statement can unexpectedly create or assign to a variable already in the current workspace, overwriting existing
data.
Concatenating strings within an eval statement is often difficult to read. Other language constructs can simplify the syntax in your
code.
The "safer" alternative is the function assignin:
The following will do exactly what you want:
letter = 'C';
numbers = 1:3;
arrayfun(#(x) assignin('base',[letter num2str(x)],[]),numbers)
I know cases where you need to create variables likes this, but in most cases it is better and more convenient to use cell arrays or structs.
The trick is to use a cell array:
k=3
C=cell(k,1)
for t=1:k
C{t}= rand(t)
end
If each matrix is of equal size, you would probably just want a three dimensional matrix rather than a cell array.
You now have one cell array,but can access the matrices like this:
C{2} %Access the second matrix.
The use of eval is almost inevitable in this case:
k = 3;
for i = 1:k
eval(sprintf('C%d = [];', i));
end;
Mind you that generating variable names for data storage rather than indexing them (numerically -- see the solution of Dennis Jaheruddin based on cell arrays -- or creating a dynamic struct with named fields that store the data) is almost always a bad idea. Unless you do so to cope up with some weird scripts that you don't want to / cannot modify that need some variables already created in the global workspace.

In Matlab, how to quickly select single element of matrix produced by a function? [duplicate]

This question already has answers here:
How can I index a MATLAB array returned by a function without first assigning it to a local variable?
(9 answers)
Closed 8 years ago.
E.g. I have the output of cov(A,B), which is a 2×2 matrix.
I want to select the element in position 2,1 of the matrix.
I can do this by blah = cov(A,B) and then select blah(1,2).
This isn't the most efficient way to do it though, and I'd prefer to do it in one line. Is there a way to do that?
You can try using getfield():
getfield(cov(A,B), {1,2})
The performance difference between this and what you have currently will likely be negligible, however. I personally would prefer just using that temporary variable.
<stealing brilliance from Amro>
You can also do this:
C = builtin('_paren', cov(A,B), 2, 1);
</stealing brilliance from Amro>

update struct via another struct in Matlab [duplicate]

This question already has answers here:
What are some efficient ways to combine two structures in MATLAB?
(5 answers)
Closed 8 years ago.
I'm wondering if there is a convenient way to update a struct with the values of another struct in Matlab.
Here is the code, with the use of fieldnames, numel and a for loop,
fn = fieldnames(new_values);
for fi=1:numel(fn)
old_struct.(fn{fi}) = new_values.(fn{fi});
end
Of course, I don't want to loose the fields in old_struct that are not in new_values, so I can't use the simple old_struct=new_values.
Updating a struct is something we may want to do in a single short line in an interpreter.
Since you are convinced that there is no simpler way to achieve what you want, here is the method described in Loren Shure's article (see link posted in Dan's comment), applied to your example:
%// Remove overlapping fields from first struct
s_merged = rmfield(s_old, intersect(fieldnames(s_old), fieldnames(s_new)));
%// Obtain all unique names of remaining fields
names = [fieldnames(s_merged); fieldnames(s_new)];
%// Merge both structs
s_merged = cell2struct([struct2cell(s_merged); struct2cell(s_new)], names, 1);
Note that this slightly improved version can handle arrays of structs, as well as structs with overlapping field names (this is what I believe you call collision).

Matlab get string containing variable name [duplicate]

This question already has answers here:
print variable-name in Matlab
(4 answers)
Closed 9 years ago.
In Matlab, how can i get a String containing "GRUMPY" given the following declaration:
GRUMPY = 500;
This is usually called reflection in other programming languages, but i cannot find an example of it in Matlab.
MATLAB doesn't provide built-in functionality for this, but there is a workaround, as employed here
Essentially, you have to create your own function to do this. Take advantage of Matlab's functionality for getting the variable name of the INPUT ARGUMENT to a function.
I.e.
function out = varname(var)
out = inputname(1);
end
Then
GRUMPY = 500;
name = varname(GRUMPY)
will give you what you want.
If I understand correctly you should try
who GRUMPY
or
which GRUMPY