有没有更优雅的方式来编写这些循环?

Is there a more elegant way to write these loops?

我有一个脚本需要一些参数才能 运行。我有兴趣探索参数变化时的结果,所以我在顶部定义了几个 scan 数组,将整个代码包装在多个 for loops 中并将参数值设置为当前扫描值。

这很容易出错而且不优雅。更改代码的过程是:1) 在顶部重置 scan 变量,2) 注释掉例如 b = scan2(j2) 和 3) 取消注释 b=b0

允许将变量设置为数组以及随后 运行 所有此类组合的代码的更好方法是什么? 现在我的代码示例:

close all
clear all

%scan1 = linspace(1,4,10);
scan1 = 0;
scan2 = linspace(0,1,10);
scan3 = linspace(-1,0,10);

for j3 = 1:length(scan3)
  for j2 = 1:length(scan2)
    for j1 = 1:length(scan1)

      a = a0;
      %b = scan2(j2);
      b = b0;
      %c = c0;
      c = scan3(j3);
      d = scan2(j2);

      %(CODE BLOCK THAT DEPENDS ON variables a,b,c,d...)

    end

  end

end

一种方法是使用 ndgrid 制作一个包含所有参数组合的向量。对于足够大的参数扫描,这可能会成为内存问题,但至少在其他方面更清晰,只需要一个循环,代码后面不需要 re-assignments:

a0vec = 1;
b0vec = linspace(1,4,4);
c0vec = linspace(11,15,5);
d0vec = linspace(101,104,4);
e0vec = 5;

[a0s,b0s,c0s,d0s,e0s] = ndgrid(a0vec,b0vec,c0vec,d0vec,e0vec);    
N = numel(a0s);

for j = 1:N

    a0 = a0s(j);
    b0 = b0s(j);
    c0 = c0s(j);
    d0 = d0s(j);
    e0 = e0s(j);

    %__ (CODE THAT DEPENDS ON a0 - e0 here) __

end

仍然希望看到您的建议!

基于this idea用一个for循环模拟多个循环,我试着适应你的情况。虽然实现了良好的内存效率和可用性,但此解决方案比使用单独的 for 循环要慢。

%define your parameters
p.a = 1;
p.b = linspace(1,4,4);
p.c = linspace(11,15,5);
p.d = linspace(101,104,4);
p.e = 5;
iterations=structfun(@numel,p);
iterator=cell(1,numel(iterations));
for jx = 1:prod(iterations)
    [iterator{:}]=ind2sub(iterations(:).',jx);%.'
    %This line uses itertor to extract the corresponding elemets of p and creates a struct which only contains scalars.
    q=cell2struct(cellfun(@(a,b)(a(b)),struct2cell(p),iterator(:),'uniform',false),fieldnames(p));
    %__ (CODE THAT DEPENDS ON q.a to q.e here) __

end

对于我测试的场景,每次迭代增加的计算开销低于 0.0002s,总共 0.0002.*prod(iterations)s。