【问题标题】:When is it appropriate to use a cell array vs. a struct in Matlab?什么时候适合在 Matlab 中使用元胞数组与结构?
【发布时间】:2010-09-03 13:00:59
【问题描述】:

如果我想在一个变量中存储一些不同大小的字符串或矩阵,我可以考虑两种选择:我可以创建一个结构数组并让其中一个字段保存数据,

structArray(structIndex).structField

或者我可以使用元胞数组,

cellArray{cellIndex}

但是对于何时使用哪种数据结构有一个通用的经验法则吗?我想知道在某些情况下使用其中一种是否有缺点。

【问题讨论】:

    标签: arrays matlab struct cell


    【解决方案1】:

    在我看来,这更多是为了方便和代码清晰。问问自己,您更喜欢按数字还是按名称来引用变量元素。然后在前一种情况下使用单元数组,在以后使用结构数组。想一想,就好像你有一个有和没有标题的表格。

    顺便说一句,您可以使用CELL2STRUCTSTRUCT2CELL 函数在结构和单元格之间轻松转换。

    【讨论】:

    • 对于单元格数组,您需要一些元数据来识别单元格内容。精心选择的字段名称使您的代码自我解释。
    【解决方案2】:

    如果您在函数中使用它进行计算,我建议您使用元胞数组,因为它们更方便处理,例如谢谢到CELLFUN

    但是,如果您使用它来存储数据(并返回输出),最好返回结构,因为字段名称(应该)是自记录的,因此您不需要记住您在单元格数组的第 7 列。此外,您可以轻松地在结构中包含一个“帮助”字段,如果需要,您可以在其中对这些字段进行一些额外的说明。

    结构对于数据存储也很有用,因为如果您想在以后更新代码,可以用对象替换它们而无需更改代码(至少在您预先分配结构的情况下) .它们具有相同的语法,但对象将允许您添加更多功能,例如依赖属性(即基于其他属性动态计算的属性)。

    最后,请注意单元格和结构会为每个字段增加几个字节的开销。因此,如果您想使用它们来处理大量数据,最好使用包含数组的结构/单元,而不是使用字段/元素仅包含标量的大型结构/单元数组。

    【讨论】:

      【解决方案3】:

      这段代码表明元胞数组的赋值和检索速度大约是结构体的两倍。我没有将这两个操作分开。可以很容易地修改代码来做到这一点。

      之后运行“whos”表明他们使用的内存量非常相似。

      我的目标是用 Python 术语制作一个“列表列表”。也许是“数组数组”。

      我希望这很有趣/有用!

      %%%%%%%%%%%%%%  StructVsCell.m %%%%%%%%%%%%%%%
      
      clear all
      
      M = 100; % number of repetitions
      N = 2^10; % size of cell array and struct
      
      
      for m = 1:M
          % Fill up a template cell array with
          % lists of randomly sized matrices with
          % random elements.
          template{N} = 0;
          for n = 1:N
              r1 = round(24*rand());
              r2 = round(24*rand());
              r3 = rand(round(r2*rand),round(r1*rand()));
              template{N} = r3;
          end
      
          % Make a cell array equivalent
          % to the template.
          cell_array = template;
      
          % Create a struct with the
          % same data.
          structure = struct('data',0);
          for n = 1:N
              structure(n).data = template{n};
          end
      
          % Time cell array
          tic;
          for n = 1:N
              data = cell_array{n};
              cell_array{n} = data';
          end
          cell_time(m) = toc;
      
          % Time struct
          tic;
          for n = 1:N
              data = structure(n).data;
              structure(n).data = data';
          end
          struct_time(m) = toc;
      end
      
      str = sprintf('cell array: %0.4f',mean(cell_time));
      disp(str);
      str = sprintf('struct: %0.4f',mean(struct_time));
      disp(str);
      str = sprintf('struct_time / cell_time: %0.4f',mean(struct_time)/mean(cell_time));
      disp(str);
      
      % Check memory use
      whos
      
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      

      【讨论】:

      • 哦,感谢@jonas 告诉我有关 CELLFUN 的信息。我不知道该函数,并将在我现在正在处理的代码中使用它。
      • 根据您的代码 struct 在我的情况下要快四倍
      【解决方案4】:

      首先,我赞同 yuk 的回答。从长远来看,清晰度通常更为重要。

      但是,根据数据的不规则形状,您可能还有两个选择:

      选项 3:structScalar.structField(fieldIndex)

      选项 4:structScalar.structField{cellIndex}

      在这四个中,#3 对大量元素的内存开销最小(它最小化了矩阵的总数),我的意思是大于 100,000。如果您的代码适合在 structField 上进行矢量化,那么它也可能是性能上的胜利。如果您无法将structField 的每个元素收集到单个矩阵中,则选项 4 具有符号优势,但没有选项 3 的内存和性能优势。这两个选项都可以更轻松地在整个数据集上使用 arrayfun 或 cellfun,代价是要求您分别从每个字段中添加或删除元素。选择取决于您如何使用您的数据,这让我们回到 yuk 的答案——选择最清晰的代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-08
        • 1970-01-01
        • 2019-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多