如何根据输入参数的数量动态创建嵌套循环
How to create nested loops dynamically depending on number of input arguments
我正在尝试使用一个函数绘制数据 table,其中每个系列都被视为一组符合特定标准的数字,如下所示:
function plotter_fun(Table)
aList = unique(Table.a);
bList = unique(Table.b);
cList = unique(Table.c);
for a = aList
for b = bList
for c = cList
Slice = Table(Table.a==a & Table.b==b & Table.c==c, :);
plot(Slice.x, Slice.y);
end
end
end
end
我想这样做,以便 table header 参数('a'、'b'、'c')可以作为参数传入, 并且可以是任意数量的参数。期望的结果类似于:
function plotter_fun(Table, headerNames)
for i = 1:numel(headerNames)
loopList{i} = unique(Table.(headerNames{i}));
end
% do nested looping
end
在哪里这样称呼:
plotter_fun(Table, {'a', 'b', 'c'});
我不确定如何使用递归循环算法,以便可以动态更改嵌套循环的数量?
看起来每个切片都是您的 header 变量值的独特组合。考虑到这一点,我们可以使用 findgroups
和 unique
来完全消除循环。那么"dynamic nesting"的情况就不是问题了...
此功能如您所描述的那样工作:
function plotter_fun(Table, headerNames)
% Create a matrix of group indices for each specified header
grps = zeros(size(Table,1), numel(headerNames));
for i = 1:numel(headerNames)
grps(:,i) = findgroups(Table.(headerNames{i}));
end
% Get the unique rows for the grouping variables
[~, ~, idx] = unique(grps, 'rows');
% Loop over each unique row index and slice out the specified rows.
for i = 1:max(idx)
Slice = Table( idx == i, : );
plot( Slice.x, Slice.y );
end
end
测试(这在删除 plot
行时有效,因为我没有指定 x
或 y
列):
tbl = cell2table( {'a', 1, 'dog';
'a', 2, 'cat';
'b', 3, 'cat';
'a', 2, 'cat'}, ...
'variablenames', {'char','num','pet'} )
plotter_fun( tbl, {'char', 'num', 'pet'} ) % output slices are rows [1], [2,4] and [3].
plotter_fun( tbl, {'char'} ) % output slices are rows [1,2,4] and [3].
编辑:
这是从 Slice
到 auto-generate "filter" 标签的灵活方法。我们可以在 headerNames
和 table 值之间连接 =
(如果有数值,则使用 num2str
转换),然后使用 strjoin
生成我们的标签每个标题用 ,
分隔。
一个衬里看起来像这样,将在定义 Slice
的循环中使用:
label = strjoin( strcat( headerNames', '=', ...
cellfun(@num2str,table2cell(Slice(1,headerNames)),'uni',0)' ), ', ');
% Output for Slice 1 of example 1 above: 'char=a, num=1, pet=dog'
% Output for Slice 1 of example 2 above: 'char=a'
% cellfun(@num2str, __ ) conversion not needed if there is no numeric data in the table
我正在尝试使用一个函数绘制数据 table,其中每个系列都被视为一组符合特定标准的数字,如下所示:
function plotter_fun(Table)
aList = unique(Table.a);
bList = unique(Table.b);
cList = unique(Table.c);
for a = aList
for b = bList
for c = cList
Slice = Table(Table.a==a & Table.b==b & Table.c==c, :);
plot(Slice.x, Slice.y);
end
end
end
end
我想这样做,以便 table header 参数('a'、'b'、'c')可以作为参数传入, 并且可以是任意数量的参数。期望的结果类似于:
function plotter_fun(Table, headerNames)
for i = 1:numel(headerNames)
loopList{i} = unique(Table.(headerNames{i}));
end
% do nested looping
end
在哪里这样称呼:
plotter_fun(Table, {'a', 'b', 'c'});
我不确定如何使用递归循环算法,以便可以动态更改嵌套循环的数量?
看起来每个切片都是您的 header 变量值的独特组合。考虑到这一点,我们可以使用 findgroups
和 unique
来完全消除循环。那么"dynamic nesting"的情况就不是问题了...
此功能如您所描述的那样工作:
function plotter_fun(Table, headerNames)
% Create a matrix of group indices for each specified header
grps = zeros(size(Table,1), numel(headerNames));
for i = 1:numel(headerNames)
grps(:,i) = findgroups(Table.(headerNames{i}));
end
% Get the unique rows for the grouping variables
[~, ~, idx] = unique(grps, 'rows');
% Loop over each unique row index and slice out the specified rows.
for i = 1:max(idx)
Slice = Table( idx == i, : );
plot( Slice.x, Slice.y );
end
end
测试(这在删除 plot
行时有效,因为我没有指定 x
或 y
列):
tbl = cell2table( {'a', 1, 'dog';
'a', 2, 'cat';
'b', 3, 'cat';
'a', 2, 'cat'}, ...
'variablenames', {'char','num','pet'} )
plotter_fun( tbl, {'char', 'num', 'pet'} ) % output slices are rows [1], [2,4] and [3].
plotter_fun( tbl, {'char'} ) % output slices are rows [1,2,4] and [3].
编辑:
这是从 Slice
到 auto-generate "filter" 标签的灵活方法。我们可以在 headerNames
和 table 值之间连接 =
(如果有数值,则使用 num2str
转换),然后使用 strjoin
生成我们的标签每个标题用 ,
分隔。
一个衬里看起来像这样,将在定义 Slice
的循环中使用:
label = strjoin( strcat( headerNames', '=', ...
cellfun(@num2str,table2cell(Slice(1,headerNames)),'uni',0)' ), ', ');
% Output for Slice 1 of example 1 above: 'char=a, num=1, pet=dog'
% Output for Slice 1 of example 2 above: 'char=a'
% cellfun(@num2str, __ ) conversion not needed if there is no numeric data in the table