【问题标题】:Efficiently iterate in cell在单元格中有效地迭代
【发布时间】:2014-08-07 05:23:46
【问题描述】:

如何在单元格中高效地迭代?

我有一个这样的单元格:

H{i,j} = 

{1} {2} {3} {4} ...
{5} {6} {7} {8} ...
....

实际尺寸为~300*300,只有~1000个非空项。

for i = 1 : numel(H)
    if isempty(H{i}), continue, end
    for j = 1 : numel(H)
        if i==j || isempty(H{j}), continue, end
            COMPLEX_OPERATION(H{i}, H{J});
        end
    end
end

这是对单个单元格的两层(请原谅我的英语)迭代。

结果证明这段代码效率低下。

在迭代中浪费了太多时间。

我正在尝试找到一种有效的方法来执行此迭代。

一种可能的解决方案是使用 cellfun(@COMPLEX_OPERATION),但我不确定如何使用 cellfun 执行此双循环。

另一种可能的解决方案是首先修剪空单元格。但是我不确定这是否会在很大程度上解决这个问题。

【问题讨论】:

  • 你正在循环你的数据,只有当两个元素(H{i}H{j})都不为空时你才想做COMPLEX_OPERATION(),其他时候你什么都不想做。但是你不想做COMPLEX_OPERATION(H{i}, H{i});COMPLEX_OPERATION(H{i}, H{j}); 和之后的COMPLEX_OPERATION(H{j}, H{i});你想同时做吗?
  • 不清楚您是如何存储数据的。这可能不是一种有效的开始方式。解决您存储它的方式,将解决您当前和未来的大部分问题。如果每个单元格都有一个标量,那么根本没有理由使用单元格数组。
  • 我同意。您不应该将元胞数组用于单个值。此外,您不应使用 ij 作为变量,因为它们用于表示复数。

标签: matlab iteration cell


【解决方案1】:

这也应该很有趣。使用对 cellfun 的双重调用来获取所有组合。只需通过您的 complex_function 更改 C1+C2

%simulation
H=cell(300,300);
indx=randperm(numel(H));
[H{indx(1:1000)}]=deal(1);

%code you want
empty_H=cellfun(@isempty, H);
non_empty_H=H(~empty_H);
all_combinations=cellfun(@(C2) (cellfun(@(C1) C1+C2, non_empty_H, 'UniformOutput', false)), non_empty_H, 'UniformOutput', false);

【讨论】:

  • 请注意,这将使组合 (i==j) 比您需要的多 1000 个(与 for 循环相反)。尽管如此,由于使用了cellfun,它可能会有所改善。如有必要,您可以在内部 cellfun 中轻松删除它,而不会对组合进行解释
【解决方案2】:

你为什么不能这样做

ind = ~cellfun(@isempty, H).* ~eye(size(H))

ind =

   0   1
   0   0

[r,c] = find(ind==1);
cellfun(@(H,r,c) (whatever_your_complex_function_does), H{[find(ind==1)].'}, cell2mat(r,[1 1]),cell2mat(c,[1 1]);



更长的解释...

H ={[],[1 2]; [] [3 4]}



ind = cellfun(@isempty, H)

ind =

   1   0
   1   0

那些是空索引。我们将在最后反转它们。

接下来,找到i=j 所在的位置。然后我们将在最后排除它们。

创建一个表示i=j 的身份矩阵。

I = eye(size(ind))

I =   

   1   0
   0   1

然后将它们与 ind 相乘。我们使用~I 来获取i~=j(~ind) 所在的位置,以便获取非空元素。

(~ind).*~I

ans =

0   1
0   0

现在您已经获得了H 不为空和i~=j 的索引。

获取这些的下标。

[r,c] = find(ind==1);

然后您创建一个匿名函数,该函数采用与这些下标相对应的H 的值并将其逐元素应用于HHrc 将用作匿名函数的输入,您可以将其用作 H{r}H{c}

cellfun(@(H,r,c) (whatever_your_complex_function_does), H{[find(ind==1)].'}, cell2mat(r,[1 1]),cell2mat(c,[1 1]);

【讨论】:

  • 我认为他想要每个元素的COMPLEX_OPERATION 与其他元素(相同除外)。因此,通过拥有1000 非空元素,他将拥有1,000,000 次COMPLEX_OPERATION 的转换。他能用cellfun(@COMPLEX_OPERATION, H{indH}, H{indH}) 解决这个问题吗? COMPLEX_OPERATION 是应用于第 n 个元素和第 n 个元素还是应用于第 n 个元素和其他元素?
  • 已更新以反映这一点。谢谢。
  • 不完全像@TheMinion 所说的那样。如果我是对的,COMPLEX_OPERATION 不会被投射 1,000,000 次。
  • 恐怕我的问题有点误导。正如@TheMinion 建议的那样,我实际上期待在单个单元格之间执行双循环而不是迭代。 (他在这方面的权利。)
  • @SolessChong 我不确定你所说的双循环是什么意思,但我已经更新了我认为会反映你的伪代码的答案。只有一个对 cellfun 的调用会在提供索引的情况下按元素应用您的 COMPLEX_FUNCTION。
猜你喜欢
  • 1970-01-01
  • 2019-06-14
  • 2012-08-12
  • 2012-09-21
  • 1970-01-01
  • 1970-01-01
  • 2014-01-19
  • 1970-01-01
  • 2019-02-24
相关资源
最近更新 更多