这个简单的示例提供了一些关于自我开始使用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。因此,它是规则的,可以保存在向量中。无需使用单元格类。