I have a cell array with strings and a numeric array in Matlab. I want every entry of the cell array to be concatenated with the number from the corresponding position of the array. I think that it can be easily solved using cellfun, but I failed to get it to work.
To clarify, here is an example:
c = {'121' '324' '456' '453' '321'};
array = 1:5
I would like to get:
c = {'1121' '2324' '3456' '4453' '5321'}
A special version of sprintf that outputs directly to a cell array is called sprintfc:
>> C = sprintfc('%d%d',[array(:) str2double(c(:))]).'
C =
'1121' '2324' '3456' '4453' '5321'
It is also a bit different in the way it handles array inputs, by preserving the shape.
You're correct, you can use cellfun – you just need to convert the array to a cell array as well using num2cell. Assuming array is a vector of integers:
c = {'121' '324' '456' '453' '321'};
array = 1:5;
c2 = cellfun(#(c,x)[int2str(x) c],c,num2cell(array),'UniformOutput',false)
which returns
c2 =
'1121' '2324' '3456' '4453' '5321'
In your case, you can also accomplish the same thing just using cell2mat and mat2cell:
c2 = mat2cell([int2str(array(:)) cell2mat(c.')],ones(1,length(array))).'
Another one-liner, this one without undocumented functions (with thanks to #chappjc for showing me the "format" input to num2str):
strcat(num2str(array(:),'%-d'),c(:)).'
Related
I currently have a cell array consisting of 7x1 vectors. I need to extract the first element (1,1) of each vector from each cell and store these values in a new array. This is what I currently have:
for j = 1:numel(xvalues)
cellj = xvalues{j};
a = cellj(1:1);
avalues(1:j) = a;
end
However, I am just generating a cell array with the first element of the last cell, repeating.
How can I fix this?
You can also use cellfun to apply a function to each element in a cell array. So to extract the first element of each vector the following should work.
avalues = cellfun(#(x) x(1),xvalues);
Cellfun loops through each element in the cell array and passes it in to the anonymous function via #(x). We then process x by taking the first element x(1).
In cases such as yours, where the cell contents are matrices of the same size, and assuming your inputs are small enough (meaning that neither memory nor runtime are imminent issues) you can convert the cell array into a numeric matrix and select a vector along the relevant dimension:
function out = q48740494
%% Generate some data:
c = squeeze(num2cell(randi(20,7,1,20),[1,2]));
% c = 20×1 cell array of {7x1 double}
%% Convert this into a numeric array and output:
out = cell2mat(c.'); out = out(1,:);
% BONUS: another version of the line above.
% out = subsref(cell2mat(c.'), substruct('()', {1,1:numel(c)}) ) ;
I have a for loop and each value a{i} b{i} c{i} is equal each time with a specific number. So I was wondering how can I put all those value in an array through loop. The way that I am using I mean this one [a{i};b{i};c{i}] it seems that it doesn't work! If I keep 2 out of three values is working but I want the data from all of the values (a b c)
You can see the (pseudo)code below:
for i=1:number of cells
Cell{i}.Tri=[a{i};b{i};c{i}]
end
cell2mat is what you need:
a = num2cell(rand(1,10));
b = num2cell(rand(1,10));
c = num2cell(rand(1,10));
abc = cell2mat([a;b;c]);
This can be done without a for loop by using cellfun combined with the cat function. EDIT: As noted in the comments, cellfun is itself a loop.
% Create all variables
a{1}=rand(10);
a=repmat(a,10,1);
b=a;
c=a;
% Add a cell array of equal size to a. The contents of each cell are the dimension along which to concatenate.
catarg=num2cell(ones(size(a)))
% Do the concatenation
d=cellfun(#cat,catarg,a,b,c,'UniformOutput',false);
I want to extract some certain values from a simple cell-array, which looks like:
CellExample{1} = [1,54,2,3,4]
CellExample{2} = [1,4,1,92,9,0,2]
...
And I have an additional array that tells me which element I want to extract from each Cell element. The array is as long as the cell:
ArrayExample = [2,4,...]
Basically, I want an array that says:
Solution(1) = CellExample{1}(ArrayExample(1)) = 54
Solution(2) = CellExample{2}(ArrayExample(2)) = 92
I have thought of using cellfun, but I have still some troubles using it correctly, e.g.:
cellfun(#(x) x{:}(ArrayExample),CellExample,'UniformOutput',false)
The following
Cell{1} = [1,54,2,3,4]
Cell{2} = [1,4,1,92,9,0,2]
cellfun(#(x) disp(x), Cell)
is equivalent to the loop
for ii = 1:numel(Cell)
disp(Cell{ii})
end
that is, cellfun() already passes the content of each cell to the anonymous function.
However, since you want to pass a numeric array as the second input to the anonymous function, and cellfun() accepts only cell() inputs, you need to use arrayfun(), which does NOT unpack cell content.
In your case:
arrayfun(#(c,pos) c{1}(pos), Cell, Array)
and it is equivalent to:
for ii = 1:numel(Cell)
Cell{ii}(Array(ii))
end
I am trying to carry out the intersection of two arrays in Matlab but I cannot find the way.
The arrays that I want to intersect are:
and
I have tried:[dur, itimes, inewtimes ] = intersect(array2,char(array1));
but no luck.
However, if I try to intersect array1 with array3 (see array3 below), [dur, itimes, inewtimes ] = intersect(array3,char(array1));the intersection is performed without any error.
Why I cannot intersect array1 with array2?, how could I do it?. Thank you.
Just for ease of reading, your formats for Arrays are different, and you want to make them the same. There are many options for you, like #Visser suggested, you could convert the date/time into a long int which allows faster computation, or you can keep them as strings, or even convert them into characters (like what you have done with char(Array2)).
This is my example:
A = {'00:00:00';'00:01:01'} %//Type is Cell String
Z = ['00:00:00';'00:01:01'] %//Type is Cell Char
Q = {{'00:00:00'};{'00:01:01'}} %//Type is a Cell of Cells
A = cellstr(A) %//Convert CellStr to CellStr is essentially doing nothing
Z = cellstr(Z) %//Convert CellChar to CellStr
Q = vertcat(Q{:,:}) %// Convert Cell of Cells to Cell of Strings
I = intersect (A,Z)
>>'00:00:00'
'00:01:01'
II = intersect (A,Q)
>>'00:00:00'
'00:01:01'
This keeps your dates in the format of Strings in case you want to export them back into a txt/csv file.
Your first array would look something like this:
array1 = linspace(0,1,86400); % creates 86400 seconds in 1 day
Your second array should be converted using datenum, then use cell2mat to make it a matrix. Lastly, use ismember to find the intersection:
InterSect = ismember(array2,array1);
In matlab I have the following 2 data structures b and c defined as follows.
b(1).b = struct('c',{'a', 'b', 'c'})
c(1).b = struct('c',{'b', 'a', 'c'})
Now I want to use ismember to find out if the elements of b(1).b.c are contained in c(1).b.c and if so, which indices of c(1).b.c each of the elements belong to.
For example: b(1).b(1).c = a, I want to backtrace this to structure c to find which index of structure c 'a' belongs to (it should return 2 since 'a' is the second element of structure c).
I have tried
[~, ind] = ismember({b(1).b.c},{c(1).b.c})
which has worked for me previously with a different data structure but I now receive the following error:
*Error using cell/ismember>cellismemberR2012a (line 192)
Input A of class cell and input B of class cell must be cell arrays of strings, unless one is a string.
Error in cell/ismember (line 56)
[varargout{1:max(1,nargout)}] = cellismemberR2012a(A,B);*
I am not sure why its not working. Does anybody know how to fix this?
Thanks.
Googling around did not show any possible solutions but there are couple options:
[~, ind] = ismember([{b(1).b.c}],[{c(1).b.c}])
and casting to cell array:
[~,idx]=ismember(struct2cell(b(1).b),struct2cell(c(1).b))
idx=reshape(idx,1,3);
For both output should be:
2 1 3
I found the following to work.
First assigning b(1).b.c to an array S and then comparing that with the data structure c using ismember.
S = [b(1).b.c]
S = S'
[~, ind] = ismember(S,{c(1).b.c})
I have found this to work.
Also,
[~, ind] = ismember([b(1).b.c}],[c(1).b.c])
does not give an error but all the values in ind are zero which is not true for the data.
Thanks all for your input!