Access structure array whose index is stored in a string - arrays

I want to get a value from a structure array by code, and I'll have the index stored in a string.
I've tried to run this code:
function M = getdata(matrix,field,varargin)
exp = [];
for i = 1:nargin-3
exp = [exp num2str(varargin{i}) ','];
end
exp = [exp num2str(varargin{nargin-2})];
M = eval('matrix(exp).(Field)');
end
However, it fails.
For example, suppose I have a structure array with 2 fields, A and B. So, I could write
MyStruct(1,1).A
A possible use would be:
M = getdata(MyStruct,A,1,1)
and I want the program to do:
M = MyStruct(1,1).A
How could I do that?
Thanks!

You can use the getfield function:
M = getfield(MyStruct, {1,1} ,'A');
Or if you wanted, say, MyStruct(1,1).A(3).B:
M = getfield(MyStruct, {1,1}, 'A', {3},'B');

For the example you give, this will suffice:
function M = getdata(matrix,field,varargin)
M = matrix(varargin{:}).(field);
which you call like
getdata(myStruct, 'A', 1,1)
which makes that function pretty useless.
But, in general, when you have indices given as strings, you can follow roughly the same approach:
%// Your indices
str = {'1', '2'};
%// convert to numbers
str = cellfun(#str2double, str, 'UniformOutput', false);
%// use them as indices into structure
M = myStruct(str{:}).(field)
And if you really insist, your call to eval is just wrong:
M = eval(['matrix(' exp ').(' field ')']);
And, as a general remark, please refrain from using exp as the name of a variable; it is also the name of a built-in function (the natural exponential function).

Related

Pythonic way in matlab to decompose array to variables

So I want to decompose array to multiple variables.
For example,
I have 'data' array of (136,9) size which is of double type.
I want to decompose the values of data(1,:) to multiple variables something like below:
[frm_id,seq_id,xmin,ymin,w,h,temp1,temp2,temp3] = data(1,:);
In python it was straightforward, but above code gives following error in matlab:
Insufficient number of outputs from right hand side of equal sign to satisfy
assignment.
I can go with something like
frm_id = data(1,1);
seq_id = data(1,2);
%ect
But I do believe there must be matlab (more neat) way to do this operation.
Thanks!
You can use num2cell to convert the matrix to a cell array then copy contents of the cell to each variable:
C = num2cell(data,1);
[frm_id,seq_id,xmin,ymin,w,h,temp1,temp2,temp3] = C{:};
I can only suggest you to create a function like this:
function [frm_id,seq_id,xmin,ymin,w,h,temp1,temp2,temp3] = myfunction (data)
frm_id = data(:,1);
seq_id = data(:,2);
xmin = data(:,3);
ymin = data(:,4);
w = data(:,5);
h = data(:,6);
temp1 = data(:,7);
temp2 = data(:,8);
temp3 = data(:,9);
so in your main code
[frm_id,seq_id,xmin,ymin,w,h,temp1,temp2,temp3] = myfunction(data);

generalizing scalar inputs to array inputs for user-defined fucntions

The round function can take a scalar and operate on it. However it can also take an array and operate on it in expected manner.
>> round(2.3)
ans =
2
>> round([2.3,3.4])
ans =
2 3
I similarly have a function and want it to work in the ""expected"" manner for array inputs. It works well for scalar inputs. I could run a for loop and evaluate my function on each element of the array but what other smarter ways do i have available?
For further concreteness, i have:
function [a,b]=func(c,d,e,f)
And i have d,e,f but i want to evaluate the function to several values of c:-
g=[];
for i=1:10
[a,b]=func(c(i),d,e,f);
g=[g;[a,b]];
end
I am not fully sure how to apply arrayfun though i believe it is what i should use.
What you are looking for is the arrayfun function.
Here is the documentation: http://www.mathworks.com/help/matlab/ref/arrayfun.html
Say, I have this function:
function res = myTest(a,b)
size(a) % for checking that we work on each element
res = a+1;
res = res +b;
I have a matrix A
A = magic(3);
I want to apply myTest with a equal to each element in A
A1 = arrayfun(#(x) myTest(x,2),A)
(x is replaced by the elements of the array declared after the comma)

Creating an array with characters and incrementing numbers

Pretty simple problem, I want to create an array with char in a for loop.
code:
a = [1:5];
arr = [];
for i = 1:length(a)
arr(i) = ['f_',num2str(i)]
end
I am getting error:
In an assignment A(I) = B, the number of elements in B and I must be the same.
all i want is an array:
[f_1 f_2 f_3....]
This is because arr(i) is a single element, while ['f:', num2str(i)] contain three characters. Also, for i = 1:length(1) doesn't really make sense, since length(1) is guaranteed to be 1. I guess you wanted for i = 1:length(a). If that's the case I suggest you substitute length with numel and i with ii.
The better way to create the array you want is using sprintf like this:
sprintf('f_%i\n',1:5)
ans =
f_1
f_2
f_3
f_4
f_5
Or possiblby:
sprintf('f_%i ',1:5)
ans =
f_1 f_2 f_3 f_4 f_5
I guess this is what you really wanted:
for ii = 1:5
arr{ii} = ['f_', num2str(ii)];
end
arr =
'f_1' 'f_2' 'f_3' 'f_4' 'f_5'
Or simpler:
arr = arrayfun(#(n) sprintf('f_%i', n), 1:5, 'UniformOutput', false)
The last two can be indexed as follows:
arr{1}
ans =
f_1
You can also do (same result):
str = sprintf('f_%i\n', 1:5);
arr = strsplit(str(1:end-1), '\n')
If you're doing this to create variable names, then please don't. Use cells or structs instead.

Arrays containing text in MATLAB

In MATLAB, when code like this is implemented:
c = ['a','b','c','d'];
you can't really do anything with the elements. To illustrate my example:
>> c
c =
abcd
and when you do c(1,1) it returns A. But for c(2,1) it returns Index exceeds matrix dimensions.
To combat this problem, is there any way I could get around it? Or perhaps a different type of array?
You need to store each string in a different row, like so:
c = ['a';'b';'c';'d'];
What you have done above is use the [], which is the string concatenation operator. What it outputs is a single string, 'abcd', stored in c(1), which is why c(2) throws an index error.
Alternatively, you could use cell arrays :
c{1} = 'a';
c{2} = 'b';

How to create numeric array from a string in MATLAB?

How to create numeric array from a string in Matlab?
For example I have such a string:
>> str = dec2bin(7);
s = 111
I need the array [1 1 1]. How to do it?
I see strread function strread
but I get difficulties to use it with non-space string input.
The standard solution is to use the solution posted by yuk,
a = (str == '1');
which produces a logical result. If you need a double,
a = double(str == '1');
or even just:
a = +(str == '1');
Perhaps the simplest looking solution is this one:
a = str - 48;
although I think the last is least obvious as to what it does. I prefer code that is easy to read and understand the purpose. That goal is best met by the second solution, IMHO.
Just answered another question and found a part of it might be useful here.
You can actually convert such a string to a logical vector:
a = str == '1';
You can cast it to another type, for example double(a).
I suppose, naively:
n = length(s);
myArray = zeros(1,n)
for i = 1:n
myArray(i) = double(s(i));
where "double()" is whatever the command is for changing a string element to a double precision number, if that is indeed what you want.
With strread:
a = strread('123', '%c')
The answer is using "bitget"
> x = bitget(7,1:3);
> class(bitget(7,1:3))
ans =
double
The result is double.

Resources