Preallocating array for string concatenation - arrays

Say I have an array x of integers (0 or 1) and that I want to build a string s such that I append A if x(i)=0 and B if x(i)=1, as I loop over x. For example I could do
s = '';
for i = 1:length(x)
if x(i) == 0
s = [s 'A'];
elseif x(i) == 1
s = [s 'B'];
end
end
While this works, MATLAB complains about the array not being preallocated. How could I do this? I cannot for example do
s = zeros(1,length(x))
because then s is treated as a numeric array, and if, for example, I do s(i)='A', I just assign to s(i) the char calue of 'A'.
Any help would be greatly appreciated!

There are special functions to prealocate zeros ones or similar, but you can preallocate whatever type you want using repmat
s=repmat('_',size(x))
Besides this, you don't need a loop at all to achieve this. The simple solution:
s=repmat('_',size(x));
s(x==0)='A';
s(x==1)='B';
As you already noticed the conversion between numbers and chars, there is also a 1-line implementation.
s=char(x+'A')

Related

Array of sets in Matlab

Is there a way to create an array of sets in Matlab.
Eg: I have:
a = ones(10,1);
b = zeros(10,1);
I need c such that c = [(1,0); (1,0); ...], i.e. each set in c has first element from a and 2nd element from b with the corresponding index.
Also is there some way I can check if an unknown set (x,y) is in c.
Can you all please help me out? I am a Matlab noob. Thanks!
There are not sets in your understanding in MATLAB (I assume that you are thinking of tuples on Python...) But there are cells in MATLAB. That is a data type that can store pretty much anything (you may think of pointers if you are familiar with the concept). It is indicated by using { }.
Knowing this, you could come up with a cell of arrays and check them using cellfun
% create a cell of numeric arrays
C = {[1,0],[0,2],[99,-1]}
% check which input is equal to the array [1,0]
lg = cellfun(#(x)isequal(x,[1,0]),C)
Note that you access the address of a cell with () and the content of a cell with {}. [] always indicate arrays of something. We come to this in a moment.
OK, this was the part that you asked for; now there is a bonus:
That you use the term set makes me feel that they always have the same size. So why not create an array of arrays (or better an array of vectors, which is a matrix) and check this matrix column-wise?
% array of vectors (there is a way with less brackets but this way is clearer):
M = [[1;0],[0;2],[99;-1]]
% check at which column (direction ",1") all rows are equal to the proposed vector:
lg = all(M == [0;2],1)
This way is a bit clearer, better in terms of memory and faster.
Note that both variables lg are arrays of logicals. You can use them directly to index the original variable, i.e. M(:,lg) and C{lg} returns the set that you are looking for.
If you would like to get logical value regarding if p is in C, maybe you can try the code below
any(sum((C-p).^2,2)==0)
or
any(all(C-p==0,2))
Example
C = [1,2;
3,-1;
1,1;
-2,5];
p1 = [1,2];
p2 = [1,-2];
>> any(sum((C-p1).^2,2)==0) # indicating p1 is in C
ans = 1
>> any(sum((C-p2).^2,2)==0) # indicating p2 is not in C
ans = 0
>> any(all(C-p1==0,2))
ans = 1
>> any(all(C-p2==0,2))
ans = 0

Matlab join array of strings

In ruby and other languages, I can create an array, push an arbitrary number of strings and then join the array:
ary=[]
...
ary.push some_str
ary.push some_other_str
...
result = ary.join ""
How do I accomplish this in matlab?
User story: my plot legend is composed of a variable number of strings. The number of strings is determined runtime, so I want to declare the array, add strings dynamically and then join the array to the legend string in the end of the script.
In MATLAB, String joining happens like the following
a = 'ding';
b = 'dong';
c = [a ' ' b]; % Produces 'ding dong'
P.S. a typeof(c,'char') shows TRUE in MATLAB because it "joins" all characters into C.
Suppose you want to start with an empty char placeholder. You can do this.
a = ``; % Produces an empty character with 0x0 size.
Then you can keep adding to the end of it; like this:
a = [a 'newly added'] % produces a = "newly added"
To prove that it works, do this again:
a = [a ' appended more to the end.'] % produces a = "newly added appended more to the end."
You can always use the end keyword that points to the last index of an array, but in this case you need to append to end+X where X is the extra number of characters you are appending (annoyingly). I suggest you just use the [] operator to join/append.
There is also this strjoin(C, delim) function which joins a cell C of strings using a delim delimiter (could be whitespace or whatever). But cheap and dirty one is the one I showed above.

How do I reassign even and odd indices of a character array into a new smaller character array in Matlab?

In matlab I have a 32x1 character array A such that
A = {'F1' 'F2' 'F3' 'F4' 'F5' 'F6' ... 'F32'};
A = A';
Now I am trying to do the following with A.
For every even index of A meaning
A{2}, A{4}, A{6}...
I want to assign those values to a 16x1 character array B and for the odd indices of A I want to assign those values to a different 16x1 array C.
I use the following code:
for i=1:32
if mod(i,2)==0
B{i} = A{i};
else
C{i} = A{i};
end
end
and it works, but only partially because it assigns the right values at for e.g. B{2} and B{4} but the values in B{1} and B{3} are the same as in B{2} and B{4}.
Can anybody tell me how to reassign even and odd indices of a character array into a new smaller character array? My problem is that I am going from a 32x1 into a 16x1 and I'm not sure how to avoid the extra 16 entries.
Many thanks!
To get this question actual answered, use the idea of Luis Mendo in the comments. You can combine it with deal to save one line of code:
[B, C] = deal(A(2:2:end), A(1:2:end))
To make your loop work, you need a second running index jj:
A = {'F1' 'F2' 'F3' 'F4' 'F5' 'F6'};
for ii = 1:6
jj = ceil(ii/2);
if mod(ii,2)==0
B{jj} = A{ii};
else
C{jj} = A{ii};
end
end

Is there a more efficient way of choosing an element from 1 array and to every element of the same array

I want to, for every element of an array ZAbs, compare it for equality to every element of the array itself and put them into another distinct array. I want the distinct array's elements to have the same index as the ZAbs array.
I did this by creating 4 nested for loops:
for pAbs2 = 1:400
for qAbs2 = 1:300
zAbsCompare = ZAbs(qAbs2, pAbs2);
for pAbs3 = 1:400
for qAbs3 = 1:300
zAbsCompare2 = ZAbs(qAbs3, pAbs3);
if (zAbsCompare == zAbsCompare2)
InitialZModEqualsImag(pAbs2,qAbs2) = InitialZImag(qAbs2, pAbs2);
InitialZModEqualsReal(pAbs2,qAbs2) = InitialZReal(qAbs2, pAbs2);
end
end
end
end
end
However, this runs really slowly. I can't think of a better way to do this, but as I'm inexperienced with MATLAB there's probably something I'm overlooking here. Any help?
EDIT: Fixed an error and restated the question.
You can do the comparison (not sure that's what you want) efficently with bsxfun:
comp = bsxfun(#eq, X, shiftdim(X,-2));
The result comp(m,n,p,q) is 1 if X(m,n) == X(p,q), and 0 otherwise.

Combining array into one string (matlab)

I have something like the following:
A = [1 2 5; 1 5 7];
B = A(1,:);
I output B:
B = A(1,:);
B =
1 2 5
I am looking to combine what is contained in B into one single string:
1/2/5
You can use sprintf:
sprintf('%d/',B)
This will give you almost what you want, it will have unnecessary / in the end.
>> sprintf('%d/',B)
ans =
1/2/5/
If you want to remove it:
st = sprintf('%d/',B);
st(end) = [];
As #hmuster points out correctly, it is possible to do it with \b , the backspace character.
st = [sprintf('%d/',B) sprintf('\b')];
However, as #AndrewJanke points out correctly, it could become a problem if this string is written into a pipe or a file. So use it with caution.
If you want it done properly (IE reusable), there are two steps:
Convert your numbers to strings (this will allow later crazy values to be converted properly with num2str http://www.mathworks.com/help/matlab/ref/num2str.html
Concatenate your strings horizontally (you can use MATLAB concatenation property A = [B C]), but the functional way is strcat http://www.mathworks.com/help/matlab/ref/strcat.html

Resources