在单元格和数组上运行的有用函数
这个简单的例子提供了一些解释,我发现自从我开始使用 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%中我对文件名很感兴趣而没有别的。为了从结构数组中提取信息,我曾经创建了一个本地函数,它涉及创建正确大小的时间变量,for 循环,从每个元素中提取名称,并将其保存到创建的变量中。实现完全相同结果的更简单方法是使用上述功能之一:
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
的逻辑向量。因此,它是常规的,可以保存在矢量中; 不需要使用单元格类。