Returning the results as a vector - matlab

If I make a for-loop and return all the values in some vector in matlab as follows:
function elements(v)
for i=1:length(v)
c(i) = v(i)
end
When I run the following, I get the results as shown:
>> A = [1 2 3 4]
A =
1 2 3 4
>> elements(A)
c =
1
c =
1 2
c =
1 2 3
c =
1 2 3 4
How can I return the results as: c = [1 2 3 4] only?
Thanks.

function elements(v)
for i=1:length(v)
c(i) = v(i);
end
disp(c)

I don't know if this is gonna be what you really mean, but I'd this:
function c = so_test(v)
c = v(:)';
end

An even more compact solution
function c = elements(v)
for i=1:length(v)
c(i) = v(i);
end
Note that it does not look much different from the other solutions,
But I think that this is the what you want to do assuming you want to do something complicated/dependant on c.
If you just want all elements, just use v(:)', v or v' instead like #fpe mentioned.

Related

How to overload a Matlab operator in order for it to apply element wise to object arrays

I'm trying to define a new class with the fields object.DeltaI and object.E, and I want to define the - operator for two object as:
new_obj.E=first_obj.E
new_obj.DeltaI = first_object.DeltaI - second_obj.DeltaI
My problem is that I want this operator to work on a array of my class element wise. How do I define the operator to work element wise?
This is the class method function I wrote:
function r = minus(a,b)
if length(a.E)==length(b.E) && sum(abs(a.E-b.E)<(10^-3))==length(a.E)
r = [a];
r.DeltaI = a.DeltaI - b.DeltaI;
else
error('a.E and b.E is not in the same size or E diffrance of more than 10^-3')
end
end
simple example:
the class definition is:
classdef IV_class
properties
E
I
end
methods
function r = minus(a,b)
r = a;
r.I = a.I-b.I;
end
end
end
now when I run this code:
a(1) = IV_class;
a(1).E = [1 2 3 4];
a(1).I = [3 3 3 3];
a(2) = IV_class;
a(2).E = [1 2 3 4];
a(2).I = [1 2 1 2];
b(1) = IV_class;
b(1).E = [1 2 3 4];
b(1).I = [2 2 2 2];
b(2) = IV_class;
b(2).E = [1 2 3 4];
b(2).I = [1 1 1 1];
a(1)-b(1)
% i get the proper answer:
% ans =
%IV_class with properties:
%E: [1 2 3 4]
%I: [1 1 1 1]
a-b
% i get error:
% Error using -
%Too many input arguments.
%
%Error in - (line 13)
% r.I = a.I-b.I;
its works when i'm doing a(1)-b(1)
but not in the case of a-b
You could do it like this:
classdef IV_class
properties
E
I
end
methods (Static)
function r = minus_(a,b)
r = a;
r.I = a.I-b.I;
end
end
methods
function r = minus(a,b)
for c = 1:numel(a)
r(c) = IV_class.minus_(a(c),b(c));
end
end
end
end
Of course, you should add tests to check whether a and b have the same length, you should allocate r and so on.

How to update the length of a vector in matlab if statement

I'm using MATLAB to write a function, which can find all elements in vector v that are equal to scalar a, and change each one of them to [b c], finally return the new vector w. If v = [1 2 5], a = 2, b = 4, c = 3, then the result is w = [1 4 3 5].
Below is my code
function w = change(v, a , b ,c )
for ii = 1:length(v)
if v(ii) == a
v_1 = v(1:ii-1);
v_2 = v(ii+1:length(v));
v_3 = [b c];
v = [v_1 v_3 v_2];
end
end
w = v;
end
However, the problem is: for statement will only read the length of the v before the first run of the loop, in this way, if the size of vector is increased, then length(v) in if statement will not be updated thus ii can not cover all the element indices. For example, if my input is ([1 2 2 2 3 2 4 5 6 2], 2, 4, 4), then with my code, for will stop at ii = 10, which is length of the old v, and give a wrong result [1 4 4 4 4 4 4 3 4 4 4 5 6 2], which does not change the last element (because ii doesn't cover 15).
My question is: how to update length(v) in if statement? or is there any other better way to finish this task?
Thank you very much.
I think this will be easier if you do it with cell arrays.
function w = change(v, a , b ,c )
cellV = num2cell(v);
cellW = cellfun(#(x)(subFunction(x,a,b,c)),cellV,'uni',0);
w = [cellW{:}];
end
function out = subFunction(val,a,b,c)
if (val == a)
out = [b c];
else
out = x;
end
end
A simpler method than checking each element in a loop is to find where the new elements will go, by using find(v==a) and just loop on those cases (taking care with the indexing!):
s = find(v==a);
v(end+1:end+numel(s))=0;
for ii=1:numel(s)
ind=s(ii)+ii;
v(ind-1:end)=[b c v(ind:end-1)];
end

How to separate columns in matlab

if you have an array from a for loop
for a =1:3;
for b=1:3;
for c=1:3;
disp([a(:) b(:) c(:)])
end
end
end
and you want to separate each column of the output
to separate each column you need this code: assuming the data stored in 'A' array:
yy = A(:,1)
yx = A(:,2)
yz = A(:,3)
and so on...
but what if you don't know the size of your array or if you have m x n array? what is the general code to separate column? thanks
You can do it like this:
y = [1 1 1 1 1
1 2 3 1 1
1 0 2 2 1]
[m,n] = size(y)
for i=1:n
C{i} = y(:,i);
end
Now you can access each column via C(1), C(2), C(3), etc. C looks like this:
C =
{
[1,1] =
1
1
1
[1,2] =
1
2
0
[1,3] =
1
3
2
}
The output of just C(2) is:
ans =
{
[1,1] =
1
2
0
}
That said, it is probably better to stick with the code that you have to directly access the column from the matrix (y(:,1)), instead of creating a bunch of dynamic variables.
How would you manage these columns separated ? It's not a good idea to name them as y1, y2, ... .
If you want to pick up the i-th column, just use y(:, i). That's a lot easier to use.

how to repeat element matrix in matlab

How to repeat
A = [ 1 2 ;
3 4 ]
repeated by
B = [ 1 2 ;
2 1 ]
So I want my answer like matrix C:
C = [ 1 2 2;
3 3 4 ]
Thanks for your help.
Just for the fun of it, another solution making use of arrayfun:
res = cell2mat(arrayfun(#(a,b) ones(b,1).*a, A', B', 'uniformoutput', false))'
This results in:
res =
1 2 2
3 3 4
To make this simple, I assume that you're only going to add more columns, and that you've checked that you have the same number of columns for each row.
Then it becomes a simple combination of repeating elements and reshaping.
EDIT I've modified the code so that it also works if A and B are 3D arrays.
%# get the number of rows from A, transpose both
%# A and B so that linear indexing works
[nRowsA,~,nValsA] = size(A);
A = permute(A,[2 1 3]);
B = permute(B,[2 1 3]);
%# create an index vector from B
%# so that we know what to repeat
nRep = sum(B(:));
repIdx = zeros(1,nRep);
repIdxIdx = cumsum([1 B(1:end-1)]);
repIdx(repIdxIdx) = 1;
repIdx = cumsum(repIdx);
%# assemble the array C
C = A(repIdx);
C = permute(reshape(C,[],nRowsA,nValsA),[2 1 3]);
C =
1 2 2
3 3 4

Flattening a matrix in MATLAB with indexes

I have a matrix X e.g = [a b; c d; e f].
I need to create another matrix listing the index positions and values of the matrix.
e.g. The output is E = [ 1 1 a ; 1 2 b ; 2 1 c ; 2 2 d ; 3 1 e ; 3 2 f ]
I have been trying to use a double for loop but even if it did work, that sounds like a bad idea.
So can anyone has a better idea to perform above task?
Here is the dumbest thing I could think of (Assuming that a,b,c,d,e,f are all scalars)
x = [1 2;3 4;5 6];
[i,j]=ind2sub(size(transpose(x)), 1:numel(x));
[j(:) i(:) reshape(transpose(x),[],1)]
However, I have a feeling that there might be an answer that is more elegant.
Nothing wrong with #Andrey's answer, but because I like to find reasons to use kron :)
A = [1 2; 3 4; 5 6];
[nrows, ncols] = size(A);
M = [kron([1 : nrows]', ones(ncols, 1))...
kron(ones(nrows, 1), [1 : ncols]')...
reshape(A', [], 1)]