【问题标题】:MATLAB: Using a for loop within another functionMATLAB:在另一个函数中使用 for 循环
【发布时间】:2016-05-05 07:21:22
【问题描述】:

我正在尝试连接几个结构。我从每个结构中获取的内容取决于需要 for 循环的函数。这是我的简化数组:

t = 1;
for t = 1:5              %this isn't the for loop I am asking about
    a(t).data = t^2;     %it just creates a simple struct with 5 data entries
end

这里我手动进行拼接:

A = [a(1:2).data a(1:3).data a(1:4).data a(1:5).data]     %concatenation function

如您所见,(1:2)(1:3)(1:4)(1:5) 的范围可以循环,我尝试这样做:

t = 2;
A = [for t = 2:5
         a(1:t).data
     end]

这会导致错误“非法使用保留关键字“for”。”

如何在 concatenate 函数中执行 for 循环?我可以在 Matlab 的其他函数中执行循环吗?除了复制/粘贴该行并手动更改 1 个数字之外,还有其他方法吗?

【问题讨论】:

  • 您创建结构的代码在 matlab 中不起作用。请更新它。此外,您不能在 [] 中放置 for 循环。您缺少有关 Matlab 的基本知识。我建议阅读手册。
  • @HBHB 我刚刚运行了我从帖子中复制的代码,它对我有用。除了 [] 中的 for 循环,我现在知道它不起作用,谢谢你:)。我是这里的大新手,我承认,但有解决方法吗?在那个范围内循环真的会让我的生活更轻松。我必须对真实数据集进行大量复制粘贴。

标签: matlab


【解决方案1】:

作为gariepy回答的附录:

矩阵串联

A = [A k];

作为一种附加方式实际上很慢。每次连接到 N 大小的向量时,最终都会重新分配 N 个元素。如果您所做的只是在其末尾添加元素,则最好使用以下语法

A(end+1) = k;

在 MATLAB 中,这是经过优化的,因此平均而言,您只需重新分配矩阵中大约 80% 的元素。这可能没有太多接缝,但对于 10k 个元素,这加起来大约有一个数量级的时间差异(至少对我而言)。

请记住,这仅适用于 MATLAB 2012b 及更高版本,如本主题所述:Octave/Matlab: Adding new elements to a vector

这是我使用的代码。 tic/toc 语法不是 MATLAB 中最准确的分析方法,但它说明了这一点。

close all; clear all; clc;
t_cnc = []; t_app = [];
N = 1000;
for n = 1:N;
    % Concatenate
    tic;
    A = [];
    for k = 1:n;
        A = [A k];
    end
    t_cnc(end+1) = toc;
    % Append
    tic;
    A = [];
    for k = 1:n;
        A(end+1) = k;
    end
    t_app(end+1) = toc;
end
t_cnc = t_cnc*1000; t_app = t_app*1000; % Convert to ms

% Fit a straight line on a log scale
P1 = polyfit(log(1:N),log(t_cnc),1); P_cnc = @(x) exp(P1(2)).*x.^P1(1);
P2 = polyfit(log(1:N),log(t_app),1); P_app = @(x) exp(P2(2)).*x.^P2(1);

% Plot and save
loglog(1:N,t_cnc,'.',1:N,P_cnc(1:N),'k--',...
       1:N,t_app,'.',1:N,P_app(1:N),'k--');
grid on;
xlabel('log(N)');
ylabel('log(Elapsed time / ms)');
title('Concatenate vs. Append in MATLAB 2014b');
legend('A = [A k]',['O(N^{',num2str(P1(1)),'})'],...
       'A(end+1) = k',['O(N^{',num2str(P2(1)),'})'],...
       'Location','northwest');
saveas(gcf,'Cnc_vs_App_test.png');

【讨论】:

    【解决方案2】:

    您已经接近正确了!这会做你想做的。

    A = [];  %% note: no need to initialize t, the for-loop takes care of that
    for t = 2:5
       A = [A a(1:t).data] 
    end
    

    这似乎很奇怪……你一遍又一遍地连接相同的元素……在这个例子中,你得到了结果:

    A =
         1     4     1     4     9     1     4     9    16     1     4     9    16    25
    

    如果您真正需要的只是连接成单个数组的 .data 元素,那么这很简单:

    A = [a.data]
    

    关于此的几点说明:为什么需要括号?因为表达式

    a.data, a(1:t).data
    

    不要像许多函数那样返回单个数组中的所有数字。它们为结构数组的每个元素返回一个单独的答案。你可以这样测试:

    >> [b,c,d,e,f] = a.data
    b =
         1
    c =
         4
    d =
         9
    e =
        16
    f =
        25
    

    那里有五个不同的答案。但是 MATLAB 给了你一个秘籍——方括号!将像a.data 这样的表达式放在方括号内,突然之间,这些单独的答案被压缩到一个数组中。这是魔法

    另一个注意事项:对于非常大的数组,这里的 for 循环版本会很慢。最好提前为A分配内存。在此处的 for 循环中,MATLAB 每次都动态调整数组的大小,如果您的 for 循环有 100 万次迭代,这可能会非常慢。如果小于 1000 左右,你根本不会注意到。

    最后,HBHB 无法在顶部运行您的结构创建代码的原因是,除非您的工作区中已经定义了 a,否则它不起作用。如果你这样初始化:

    %% t = 1;  %% by the way, you don't need this, the t value is overwritten by the loop below
    a = [];   %% always initialize!
    for t = 1:5              %this isn't the for loop I am asking about
        a(t).data = t^2;     %it just creates a simple struct with 5 data entries
    end
    

    然后它第一次为任何人运行。

    【讨论】:

    • 谢谢!我现在看到它是如何工作的。它只是在每个循环中向 A 添加一个新的结构。所以我们可以把concatenate函数放在for循环里面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-06
    • 2015-12-02
    • 1970-01-01
    • 2014-03-21
    • 2022-11-18
    相关资源
    最近更新 更多