Vectorising nested for loops

1 visualización (últimos 30 días)
Melanie VT
Melanie VT el 10 de Mzo. de 2023
Movida: Stephen23 el 11 de Mzo. de 2023
Hi,
I’m trying to vectorise the following code snippet that works using the attached data. Unfortunately, I couldn’t succeed. Any ideas on how to deal with it?
Cheers,
Mel
k=0;
struct_data = struct('idx',[],'count',[],'size',[]);
for i = 1:size(table_data,1)
for j = 1:list(i)
k=k+1;
struct_data(k,1).idx = k;
struct_data(k,1).count = table_data.count(i);
struct_data(k,1).size = table_data.size(i);
end
end
  2 comentarios
Stephen23
Stephen23 el 10 de Mzo. de 2023
Are you intentionally storing lots of scalar cell arrays containing character vectors, or is the intent to actually just store the character vectors without the superfluous scalar cell arrays? If you only need the text, replace
table_data.size(i);
with
table_data.size{i};
Melanie VT
Melanie VT el 10 de Mzo. de 2023
Thank you for your contribution!

Iniciar sesión para comentar.

Respuesta aceptada

Voss
Voss el 10 de Mzo. de 2023
Editada: Voss el 10 de Mzo. de 2023
% unzip and load data
unzip data.zip
load data.mat
% run the loop method, for later comparison
k=0;
struct_data = struct('idx',[],'count',[],'size',[]);
for i = 1:size(table_data,1)
for j = 1:list(i)
k=k+1;
struct_data(k,1).idx = k;
struct_data(k,1).count = table_data.count(i);
struct_data(k,1).size = table_data.size{i}; % note this change:
% I made struct_data(k).size a char, instead of
% a scalar cell array containing a char
end
end
struct_data_save = struct_data;
% a "vectorized" method
idx = find(list);
struct_data = table2struct(removevars(table_data(repelem(idx,list(idx)),:),'district'));
C = num2cell(1:numel(struct_data));
[struct_data.idx] = deal(C{:});
% are the results the same?
isequal(struct_data,struct_data_save)
ans = logical
1
  2 comentarios
Voss
Voss el 10 de Mzo. de 2023
Editada: Voss el 10 de Mzo. de 2023
If you really want struct_data(k).size to be a 1x1 cell array containing a character vector (as in {'venti'}), as opposed to just a character vector (as in 'venti'), you can do it with a couple of additional lines of code:
% unzip and load data
unzip data.zip
load data.mat
% run the loop method, for later comparison
k=0;
struct_data = struct('idx',[],'count',[],'size',[]);
for i = 1:size(table_data,1)
for j = 1:list(i)
k=k+1;
struct_data(k,1).idx = k;
struct_data(k,1).count = table_data.count(i);
struct_data(k,1).size = table_data.size(i); % scalar cell array this time
end
end
struct_data_save = struct_data;
% a "vectorized" method
idx = find(list);
struct_data = table2struct(removevars(table_data(repelem(idx,list(idx)),:),'district'));
C = num2cell(1:numel(struct_data));
[struct_data.idx] = deal(C{:});
C = num2cell({struct_data.size});
[struct_data.size] = deal(C{:});
% are the results the same?
isequal(struct_data,struct_data_save)
ans = logical
1
Melanie VT
Melanie VT el 10 de Mzo. de 2023
That is awesome! Thank you so much for providing solutions for both scenarios🙏

Iniciar sesión para comentar.

Más respuestas (1)

Stephen23
Stephen23 el 10 de Mzo. de 2023
S = load('data.mat')
S = struct with fields:
list: [27×1 double] table_data: [27×3 table]
list = S.list
list = 27×1
0 100 60 0 0 0 0 0 0 0
tdat = S.table_data
tdat = 27×3 table
district count size ________ _____ __________ {[ 1]} 91 {'venti' } {[ 2]} 116 {'venti' } {[ 3]} 112 {'venti' } {[ 4]} 8 {'venti' } {[ 5]} 23 {0×0 char} {[ 6]} 16 {0×0 char} {[ 7]} 7 {0×0 char} {[ 8]} 1 {0×0 char} {[ 9]} 28 {0×0 char} {[10]} 58 {'tall' } {[11]} 43 {'venti' } {[12]} 13 {'trenta'} {[13]} 68 {'tall' } {[14]} 108 {'grande'} {[15]} 102 {'venti' } {[16]} 76 {'venti' }
k=0;
out0 = struct('idx',[],'count',[],'size',[]);
for i = 1:size(tdat,1)
for j = 1:list(i)
k=k+1;
out0(k,1).idx = k;
out0(k,1).count = tdat.count(i);
out0(k,1).size = tdat.size{i};
end % ^ ^ fixed indexing
end
out0
out0 = 160×1 struct array with fields:
idx count size
Without an explicit loop:
out1 = repelem(table2struct(removevars(tdat,'district')),list);
idx = num2cell(1:numel(out1));
[out1.idx] = idx{:}
out1 = 160×1 struct array with fields:
count size idx
isequal(out0,out1)
ans = logical
1
  1 comentario
Melanie VT
Melanie VT el 10 de Mzo. de 2023
Movida: Stephen23 el 11 de Mzo. de 2023
This solution is even almost 1.5 times faster than the one above! I’m truly grateful to you all🙏🏼
This post is also an Accepted Answer with appreciation😊

Iniciar sesión para comentar.

Categorías

Más información sobre Startup and Shutdown en Help Center y File Exchange.

Etiquetas

Productos


Versión

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by