I have a nested struct a of the following form
Sizes = [10, 9, 8, 11, 10];
cells = 5;
for i = 1:cells
for j = 1:40
a(i).b(j) = rand(1,1);
end
a(i).Size = Sizes(i);
end
Is it possible to put the 1:a(i).Size values of b into a cell array without using a for loop and without cellfun?
The result should look like this:
c = cell(1,cells);
for i = 1:cells
sz = a(i).Size;
c{1,i} = a(i).b(1:sz);
end
So i tried to improve on your code a little bit and you can see the results below:
%% My approach to solve the question (it has a slightly better runtime)
function c = myapproach(a, cells)
c = {a.b};
sz = [a.Size];
for i = 1:cells
c{i} = c{i}(1:sz(i));
end
end
Although this does not avoid the for loop, it has a slightly better runtime. The run-times (at cells = 50000) i got were: @yourapproach = 0.0889, @myapproach = 0.0721, @rahnema1 = 0.2329
The following is the code i used to solve this. I also made some improvements to the code you use to generate a (Marked by a comment)
function solveit()
cells = 50000;
maxVal = 40;
Sizes = randi(maxVal, 1, cells);
a(cells) = struct('Size', 0, 'b', []); %% Improved by preallocating a
for i = 1:cells
a(i).b = rand(1, maxVal); %% Improved by removing the unnecessary double loop
a(i).Size = Sizes(i);
end
fun1 = @() yourapproach(a, cells);
fun2 = @() myapproach(a, cells);
fun3 = @() rahnema1(a);
%% Show runtimes
timeit(fun1)
timeit(fun2)
timeit(fun3)
c1 = fun1();
c2 = fun2();
c3 = fun3();
%%Show approach equivalence
disp(isequal(c1, c2))
disp(isequal(c1, c3))
end
%% Your approach
function c = yourapproach(a, cells)
c = cell(1, cells);
for i = 1:cells
sz = a(i).Size;
c{1,i} = a(i).b(1:sz);
end
end
%% Approach mentioned by rahnema1
function c = rahnema1(a)
cc = struct2cell(a);
sz = [cc{1:2:end}];
sz = [sz;40-sz];
dat = [cc{2:2:end}];
c = mat2cell(dat, 1, sz(:));
c = c(1:2:end);
end
Edit: I am adding the arrayfun approach but it is at least 10 times slower than the for loop
function c = newapproach(a)
sz = [a.Size];
c = arrayfun(@(x, y) x.b(1:y), a, sz, 'UniformOutput', false);
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With