I would like to generate a string in Matlab that looks like
"BBBBBBBBBBBBBBBBCCCCCCCCCCCCCC"
where "B" is repeated m times and "C" is repeated n times. Is there any function with inputs similar to ("B","C",n,m) doing this?
You can use the function repelem to repeat the characters the wanted number of times.
str = 'BC' %This is character vector, NOT a string
n = 4; m = 3;
res = repelem(str,[n,m])
res =
'BBBBCCC'
repmat function works on char arrays, and concatenation operators too.
So:
copyfcn = #(B,C,n,m) [repmat(B,[1 n]) repmat(C,[1,m])];
copyfcn('B','C',8,4)
ans =
'BBBBBBBCCCC'
If you want the output to be a string rather than a char array, you can just wrap it in the string() function.
copyfcn2 = #(B,C,n,m) string([repmat(B,[1 n]) repmat(C,[1,m])]);
copyfcn2('B','C',8,4)
ans =
"BBBBBBBBCCCC"
You can make your own function using repmat:
>> f = #(a,b,n,m) [repmat(a, [1 m]) repmat(b, [1 m])];
>> f('B','C',12,14)
ans =
'BBBBBBBBBBBBBBCCCCCCCCCCCCCC'
Related
I have two matrices
A = [ 1 3
4 3]
B = [ 2 1
4 1 ]
I want to combine A and B to produce the string array
C = [ "1,2" "3,1"
"4,1" "3,1" ]
How can I do this in MATLAB? I tried it this way
for i = 1: 4;
for j = 1: 4;
fprintf('%0.2f,%0.2f\n',A(i,j),B(i,j) )
end
end
Appreciate your suggestions !
A = [1 3; 4 3];
B = [2 1; 4 1];
C = A + "," + B
C =
% 2×2 string array
% "1,2" "3,1"
% "4,4" "3,1"
The first thing to note, is that there is a difference between strings "string" and character arrays 'character array'. Whereas strings are one entity, the character array is an array of characters.
Thus you can make the following assignment
A(1) = "Hello";
but not
B(1) = 'Hello';
because the B(1) is one value, and 'Hello' is 5 values (H,e,l,l,o).
Secondly, you cannot use fprintf as you suggest in the comments as it only prints (as in its name) and the variable returned by fprintf is the number of characters printed. Instead, to construct the string use strcat together with num2str, such that you get:
A = rand(2); %some matrices
B = rand(2);
for i = 1:2
for j = 1:2
C(i,j) = strcat(num2str(A(i,j)),",",num2str(B(i,j)));
end
end
EDIT: If you are anyway going to interchange the comma for \pm in LaTeX, you can just do it when constructing C by using
C(i,j) = strcat(num2str(A(i,j)),"\pm",num2str(B(i,j)))
instead.
I have a simple MATLAB function outputting multiple variables:
function [a,b] = MultipleOutputs()
a = 6;
b = 8;
end
I want to assign the two output variables to 2 certain elements in an existing vector:
x = ones(1,4);
x(2:3) = MultipleOutputs()
However, this gives me:
x =
1 6 6 1
Instead of:
x =
1 6 8 1
I have had this problem in multiple cases, was never able to find the solution.
You have 2 choices:
Concatenate the vectors after outputting them separately
[a,b] = MultipleOutputs();
x = ones(1,4);
x(2:3) = [a,b];
concatenate the vectors before outputting them
function a = MultipleOutputs()
a(1) = 6;
a(2) = 8;
end
x(2:3) = MultipleOutputs();
when you run MultipleOutputs() like that in another function, it only outputs only the first element, which in this case is a.
So eventually your statement x(2:3) = MultipleOutputs() is equivalent to x(2:3) = 6.
A simple fix would be to extract all the elements:
[a,b] = MultipleOutputs();
x(2:3) = [a b];
In a previous question, a user asked about iterating over a cell array of anonymous functions. I am wondering whether there is a way to evaluate a set of functions without the explicit use of a for loop.
As an example, the following code creates an array of (simple) functions, evaluates them for a fixed value and stores the results:
fcnList = {#(x) (x+1), #(x) (x+2)};
a = 2;
for i = 1:numel(fcnList)
y(i) = fcnList{i}(a);
end
Is there a way to do this without looping?
For your example, you could do the following using the cellfun function:
fcnList = {#(x) (x+1), #(x) (x+2)};
a = 2;
cellfun(#(func) func(a),fcnList)
ans =
3 4
Where I have created a handle called func which accepts as input a function from the fcnList variable. Each function is then evaluated for a.
If you need to pass a vector instead of a scalar, for instance b, you will need to set the 'UniformOutput' option to false:
b=[3 4]
fcnList = {#(x) (x+1), #(x) (x+2)};
cellfun(#(func) func(b),fcnList,'UniformOutput',false)
ans =
{
[1,1] =
4 5
[1,2] =
5 6
}
To avoid a for loop or cellfun (which is more or less the same as a loop), you can define a single function with vector output:
fcn = #(x) [x+1, x+2];
Then fcn(a) gives you a vector cointaining the results:
>> fcn = #(x) [x+1, x+2];
>> a = 2;
>> fcn(a)
ans =
3 4
If the results of each original function have different sizes you can define a single function with cell array output:
>> fcn = #(x) {x+1, [x+2; x+3]};
>> a = 2;
>> x = fcn(a)
x =
[3] [2x1 double]
>> celldisp(x)
x{1} =
3
x{2} =
4
5
a = [1 1 1; 2 2 2; 3 3 3];
b = [1 2 3];
How can I call one function to get a vector v[i] = a[b[i],i]?
v = a(sub2ind(size(a), b, 1:length(b)))
sub2ind transforms subscripts into a single index.
Another thing to try, keeping very close to your description, you can use the arrayfun function.
First define a function that maps a value x to the desired output.
fn = #(x) a(b(x), x);
Then call that function on each input in the the i vector.
i = 1:3;
v = arrayfun(fn, i);
Or, this can all be done in a single line, in the obvious way:
v = arrayfun(#(x) a(b(x), x), 1:3);
This arrayfun is simply shorthand for the loop below:
for ixLoop = 1:3
v(ixLoop) = a(b(ixLoop),ixLoop);
end
The related functions arrayfun, cellfun, and structfun have similar uses, and are strangely empowering. This Joel article convinced me to be a believer.
I want to do
myCellArray = myCcellArray{indices}
where indices is just 0s and 1s, with same number of elements as the number of rows in myCellArray, but it doesn't work. What should I do?
You need to use parenthesis instead of curly braces to do the indexing.
>> arr = cell(2,2);
>> arr{1,1} = magic(4);
>> arr{1,2} = 'Hello';
>> arr{2,1} = 42;
>> arr{2,2} = pi;
>> arr
arr =
[4x4 double] 'Hello'
[ 42] [3.1416]
>> idx = logical(zeros(2,2));
>> idx(1,1) = true;
>> idx(2,2) = true;
>> arr(idx)
ans =
[4x4 double]
[ 3.1416]
If you want to slice a cell-array, use parentheses. Example:
%# random cellarray of strings, and a logical indices vector
myCcellArray = cellstr(num2str((1:10)','value %02d')); %'
indices = rand(size(myCcellArray)) > 0.5;
%# slicing
myCellArray = myCcellArray(indices)
What amro said is right, you should use parentheses.
But another critical thing is to use booleans not numeric 1 and 0 here.
so if you have numbers
I = [0 0 0 1 0 1]
you should use
myCellArray(I~=0)
to index it. Confusingly, a boolean array is displayed as ones and zeros in Matlab, although it is represented quite differently internally.