MATLAB在单元和阵列上运行的有用功能

示例

这个简单的示例提供了一些关于自我开始使用MATLAB以来非常有用的功能的说明:cellfun,arrayfun。这个想法是采用一个数组或单元类变量,遍历其所有元素,并在每个元素上应用专用的函数。应用函数可以是匿名的(通常是这种情况),也可以是* .m文件中定义的任何常规函数。

让我们从一个简单的问题开始,说我们需要找到给定文件夹的* .mat文件列表。对于此示例,首先让我们在当前文件夹中创建一些* .mat文件:

for n=1:10; save(sprintf('mymatfile%d.mat',n)); end

执行代码后,应该有10个扩展名为* .mat的新文件。如果我们运行命令以列出所有* .mat文件,例如:

mydir = dir('*.mat');

我们应该得到一个dir结构的元素数组;MATLAB应该为此提供类似的输出:

10x1 struct array with fields:
    name
    date
    bytes
    isdir
    datenum

如您所见,该数组的每个元素都是具有几个字段的结构。所有信息对于每个文件而言确实很重要,但是对于99%的文件名,我相当感兴趣,而没有别的。为了从结构数组中提取信息,我曾经创建一个局部函数,该函数涉及为循环创建大小正确的时间变量,从每个元素中提取一个名称,并将其保存到创建的变量中。要获得完全相同的结果,更简单的方法是使用上述功能之一:

mydirlist = arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false)
mydirlist = 
    'mymatfile1.mat'
    'mymatfile10.mat'
    'mymatfile2.mat'
    'mymatfile3.mat'
    'mymatfile4.mat'
    'mymatfile5.mat'
    'mymatfile6.mat'
    'mymatfile7.mat'
    'mymatfile8.mat'
    'mymatfile9.mat'

此功能如何工作?它通常需要两个参数:一个函数句柄作为第一个参数,以及一个数组。然后,函数将对给定数组的每个元素进行操作。第三和第四参数是可选的,但很重要。如果我们知道输出将不是常规的,则必须将其保存在单元格中。必须指出将设置false为UniformOutput。默认情况下,此函数尝试返回常规输出,例如数字向量。例如,让我们提取有关每个文件占用多少磁盘空间的信息(以字节为单位):

mydirbytes = arrayfun(@(x) x.bytes, dir('*.mat'))
mydirbytes =
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560

或千字节:

mydirbytes = arrayfun(@(x) x.bytes/1024, dir('*.mat'))
mydirbytes =
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500

这次输出是double的常规向量。UniformOutput被true默认设置为。

cellfun是类似的功能。此函数和函数之间的区别arrayfun是cellfun对单元格类变量进行操作。如果我们只希望提取给定名称为“ mydirlist”单元格中文件名列表的名称,则只需运行此函数,如下所示:

mydirnames = cellfun(@(x) x(1:end-4), mydirlist, 'UniformOutput', false)
mydirnames = 
    'mymatfile1'
    'mymatfile10'
    'mymatfile2'
    'mymatfile3'
    'mymatfile4'
    'mymatfile5'
    'mymatfile6'
    'mymatfile7'
    'mymatfile8'
    'mymatfile9'

同样,由于输出不是数字的常规向量,因此必须将输出保存在单元变量中。

在下面的示例中,我将两个函数合而为一,并且仅返回文件名列表,不带扩展名:

cellfun(@(x) x(1:end-4), arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false), 'UniformOutput', false)
ans = 
    'mymatfile1'
    'mymatfile10'
    'mymatfile2'
    'mymatfile3'
    'mymatfile4'
    'mymatfile5'
    'mymatfile6'
    'mymatfile7'
    'mymatfile8'
    'mymatfile9'

这很疯狂,但却很可能,因为arrayfun返回了预期输入为的单元格cellfun;对此的附带说明是,我们可以通过UniformOutput显式设置为false来强制其中任何一个函数在单元格变量中返回结果。我们总是可以在单元格中获得结果。我们可能无法在常规向量中获得结果。

还有就是在工作领域的结构多了一个类似的功能:structfun。我还没有发现它像其他两个一样有用,但是在某些情况下它会发光。例如,如果您想知道哪些字段是数字字段或非数字字段,则以下代码可以给出答案:

structfun(@(x) ischar(x), mydir(1))

dir结构的第一个字段和第二个字段为char类型。因此,输出为:

 1
 1
 0
 0
 0

同样,输出是true/的逻辑向量false。因此,它是规则的,可以保存在向量中。无需使用单元格类。