Main Content

访问元胞数组中的数据

基本索引

元胞数组是一种包含名为元胞的索引数据容器的数据类型。每个元胞可以包含任意类型的数据。元胞数组通常用于存放文件中不同格式的数据,例如同时包含数值和文本数据的列。

例如,假设有一个包含混合数据的 2×3 元胞数组。

C = {'one','two','three'; 
     100,200,rand(3,3)}
C=2×3 cell array
    {'one'}    {'two'}    {'three'   }
    {[100]}    {[200]}    {3x3 double}

每个元素都包含在一个元胞内。如果使用标准圆括号对该数组进行索引,得到的结果是一个包含元胞的元胞数组子集。

C2 = C(1:2,1:2)
C2=2×2 cell array
    {'one'}    {'two'}
    {[100]}    {[200]}

要向特定元胞读取或写入内容,请用花括号将索引括起来。

R = C{2,3}
R = 3×3

    0.8147    0.9134    0.2785
    0.9058    0.6324    0.5469
    0.1270    0.0975    0.9575

C{1,3} = 'longer text in a third location'
C=2×3 cell array
    {'one'}    {'two'}    {'longer text in a third location'}
    {[100]}    {[200]}    {3x3 double                       }

要同时替换多个元胞的内容,请用圆括号来引用元胞,并用花括号来定义大小相等的元胞数组。

C(1,1:2) = {'first','second'}
C=2×3 cell array
    {'first'}    {'second'}    {'longer text in a third location'}
    {[  100]}    {[   200]}    {3x3 double                       }

从多个元胞读取数据

MATLAB® 中的大多数数据处理函数都是在具有一致数据类型的矩形数组上操作的。由于元胞数组可以包含多种类型和大小,因此有时必须在处理数据之前先从元胞中提取和合并数据。本节描述一些常见的情况。

特定元胞中的文本

当整个元胞数组或已知的元胞子集包含文本时,您可以索引元胞并将其直接传递给 MATLAB 中的任何文本处理函数。例如,查找字母 tC 第一行的每个元素中出现的位置。

ts = strfind(C(1,:),'t')
ts=1×3 cell array
    {[5]}    {0x0 double}    {[8 11 18 28]}

特定元胞中的数值

处理元胞数组中数值数据的两种主要方法是:

  • 将这些元胞的内容合并成单个数值数组,然后处理该数组。

  • 分别处理单个元胞。

要合并数值元胞,请使用 cell2mat 函数。每个元胞中的数组必须具有兼容的大小,才能进行串联。例如,C 第二行的前两个元素是标量值。将它们合并为一个 1×2 数值向量。

v = cell2mat(C(2,1:2))
v = 1×2

   100   200

要处理单个元胞,可以使用 cellfun 函数。调用 cellfun 时,指定要应用于每个元胞的函数。使用 @ 符号表示它是函数,并创建一个函数句柄。例如,求 C 的第二行中每个元胞的长度。

len = cellfun(@length,C(2,:))
len = 1×3

     1     1     3

具有未知索引的元胞中的数据

当某些元胞包含要处理的数据,但您不知道确切的索引时,您可以使用以下选项之一:

  • 使用逻辑索引找到满足特定条件的所有元素,然后处理这些元素。

  • 使用 forwhile 循环一次只检查并处理一个元胞。

例如,假设您只想处理包含字符向量的元胞。要使用逻辑索引,首先使用 cellfun 函数和 ischar 来查找这些元胞。

idx = cellfun(@ischar,C)
idx = 2x3 logical array

   1   1   1
   0   0   0

然后,使用逻辑数组对元胞数组进行索引:C(idx)。索引操作的结果是一个列向量,您可以将它传递给文本处理函数,例如 strlength

len = strlength(C(idx))
len = 3×1

     5
     6
    31

另一种方法是使用循环来检查和处理每个元胞的内容。例如,查找包含字母 t 的元胞,并通过遍历这些元胞将它们合并成字符串数组。在变量 n 中跟踪循环向字符串数组添加了多少个元素。

n = 0;
for k = 1:numel(C)
    if ischar(C{k}) && contains(C{k},"t")
        n = n + 1;
        txt(n) = string(C{k});
    end
end
txt
txt = 1x2 string
    "first"    "longer text in a third location"

对多个元胞进行索引

如果使用花括号索引引用多个元胞,MATLAB 会以逗号分隔的列表形式返回元胞的内容。例如,

C{1:2,1:2}

与下列语句相同

C{1,1}, C{2,1}, C{1,2}, C{2,2}.

因为每个元胞可以包含不同类型的数据,所以无法将此列表分配给单个变量。但是,您可以将此列表分配给与元胞数量相同的变量。

[v1,v2,v3,v4] = C{1:2,1:2}
v1 = 
'first'
v2 = 100
v3 = 
'second'
v4 = 200

如果每个元胞都包含大小兼容的相同类型的数据,则可以通过将数组串联运算符 [] 应用于逗号分隔的列表来创建单个变量。

v = [C{2,1:2}]
v = 1×2

   100   200

如果元胞内容无法串联,则将结果存储在新元胞数组、表或其他异构容器中。例如,将 C 第二行中的数值数据转换为一个表。使用 C 第一行中的文本数据作为变量名称。

t = cell2table(C(2,:),VariableNames=C(1,:))
t=1×3 table
    first    second    longer text in a third location
    _____    ______    _______________________________

     100      200               {3x3 double}          

对元胞内的数组进行索引

如果元胞中包含数组,您可以使用两级索引来访问该数组中的特定元素。首先,使用花括号来访问元胞的内容。然后,对元胞中的数组使用标准索引语法。

例如,C{2,3} 返回一个 3×3 随机数矩阵。用圆括号索引以提取该矩阵的第二行。

C{2,3}(2,:)
ans = 1×3

    0.9058    0.6324    0.5469

如果元胞中包含元胞数组,请使用花括号进行索引,如果元胞中包含结构体数组,请使用圆点表示法来引用特定的字段。例如,假设一个元胞数组包含一个 2×1 元胞数组和一个标量结构体,该结构体具有包含 f1f2 两个字段

c = {'A'; ones(3,4)};
s = struct("f1",'B',"f2",ones(5,6)); 
C = {c,s}
C=1×2 cell array
    {2x1 cell}    {1x1 struct}

从嵌套的元胞数组和结构体中提取由 1 组成的数组。

A1 = C{1}{2}
A1 = 3×4

     1     1     1     1
     1     1     1     1
     1     1     1     1

A2 = C{2}.f2
A2 = 5×6

     1     1     1     1     1     1
     1     1     1     1     1     1
     1     1     1     1     1     1
     1     1     1     1     1     1
     1     1     1     1     1     1

您可以嵌套任何数量的元胞和结构体数组。对层次结构中更低的层级应用相同的索引规则。例如,当引用的元胞包含预期的元胞或结构体数组时,下面这些语法有效。

C{1}{2}{3}

C{4}.f1.f2(1)

C{5}.f3.f4{1}

不管在任何索引级别,只要您引用多个元胞,MATLAB 就会返回一个以逗号分隔的列表。有关详细信息,请参阅对多个元胞进行索引

另请参阅

| |

相关主题