CELLFUN函数常见问题解答:避坑指南,少走弯路!

吉云

最近在处理数据的时候,碰到个有点头疼的情况。手上拿到一堆数据,格式不统一,都塞在一个元胞数组(就是那个cell array)里头。有的格子里是字符串,有的里面是数字,还有的是个小矩阵,乱七八糟的。

我最初的想法,就是老老实实写个循环,一个格子一个格子地去处理。比如我想知道每个格子里头,如果是字符串,那它的长度是多少。写起来大概就是这样:先弄个空列表准备装着结果,然后用for循环从第一个格子走到一个,在循环里面先判断这个格子是不是字符串,如果是,就用length函数取长度,再存到结果列表里;如果不是,可能就记个0或者别的啥标记。

写是能写出来,但总感觉有点啰嗦,特别是当这种处理逻辑要在好几个地方用的时候,每次都写这么一段循环,代码看起来就有点臃肿,不清爽。

CELLFUN函数常见问题解答:避坑指南,少走弯路!

摸索新方法

我就琢磨着,MATLAB这么强大的工具,应该有更简便的方法?就去翻翻文档,也顺便在网上扒拉一下,看看大家是怎么处理这种批量操作元胞数组的问题的。这时候,cellfun这个函数就跳到我眼前。

看介绍说,这玩意儿能把一个函数应用到元胞数组的每个元素上。听起来正是我想要的!

开始动手试

我决定先拿个简单的例子试试水。

    CELLFUN函数常见问题解答:避坑指南,少走弯路!

  • 搞个元胞数组: 我先随手创建一个,比如 C = {'你好', '世界', '这是一个测试', '哈哈'}
  • 想干 我想获取每个字符串的长度。
  • cellfun试试: 按照说明,我试着写 lengths = cellfun(@length, C)@length 就是告诉cellfun,对每个格子都用length这个函数处理一下。

执行一下,lengths 这个变量里头,果然就得到一个包含每个字符串长度的向量,比如 [2 2 6 2] 这种。确实比我自己写循环简单多!

处理更复杂点的情况

CELLFUN函数常见问题解答:避坑指南,少走弯路!

尝到甜头后,我就想用它来解决我最初那个更复杂的问题。我的元胞数组里不光有字符串,还有数字啥的。直接用@length肯定不行,遇到数字会报错。

我想起来cellfun好像可以接受自定义的函数。那我就可以自己写个小逻辑:

  1. 先判断传进来的这个格子是啥类型。
  2. 如果是字符串,就返回它的长度。
  3. 如果不是字符串,就返回个固定的值,比如 0 或者 NaN(Not a Number)。
  4. CELLFUN函数常见问题解答:避坑指南,少走弯路!

在MATLAB里,可以直接用匿名函数(就是那个带符号,后面跟括号和表达式的)来实现这个小逻辑。我试着写类似这样的:

results = cellfun(@(x) my_custom_logic(x), my_mixed_cell_array)

这里的 my_custom_logic(x) 就是我上面说的那个判断类型、计算长度的逻辑,可以单独写成一个小函数,或者直接用 MALTAB 内置的 ischar 之类的函数在匿名函数里头写判断。

比如,一个简单的匿名函数可以写成: @(x) ischar(x)length(x)。如果x是字符,ischar(x)返回1,乘上长度就是长度;如果不是字符,ischar(x)返回0,乘上任何东西都是0。这只是个简化例子,实际逻辑可能需要更完善。

遇到的小坎坷和解决方案

CELLFUN函数常见问题解答:避坑指南,少走弯路!

在使用过程中,也碰到过一个小问题。有时候,我那个自定义函数处理完之后,返回的结果类型不统一。比如,有的格子处理完返回数字,有的返回字符串,或者有的返回空数组。

这时候直接用cellfun,它会尝试把所有结果统一成一个普通的数值数组,如果做不到,就会报错。后来发现,cellfun有个参数叫'UniformOutput'。默认情况下,它希望输出是统一格式的(值为true)。

如果我知道输出结果类型不统一,或者不确定,就可以把这个参数设成false

results = cellfun(@(x) my_complex_logic(x), my_cell_array, 'UniformOutput', false)

这样设置后,cellfun就不强求输出格式统一,它会把每个格子的处理结果再放回到一个新的元胞数组里。这样虽然结果还是个元胞数组,但至少不会报错,后续我可以再根据需要去处理这个结果元胞数组。

实践后的感受

CELLFUN函数常见问题解答:避坑指南,少走弯路!

总的来说cellfun这玩意儿用熟之后,确实挺方便的。特别是在需要对元胞数组里的每个元素执行相同操作时,代码能简洁不少。

  • 优点:代码更短,逻辑看起来更清晰,少写很多循环的模板代码。
  • 注意点:要稍微注意一下函数的输入输出,特别是当处理逻辑复杂,输出类型可能不统一时,记得用'UniformOutput', false

现在我处理类似数据时,会优先考虑能不能用cellfun来搞定。虽然它本质上可能也是循环,但写起来舒服多。分享给大家,希望对处理元胞数组感到头疼的朋友有点帮助。

CELLFUN函数常见问题解答:避坑指南,少走弯路!

免责声明:由于无法甄别是否为投稿用户创作以及文章的准确性,本站尊重并保护知识产权,根据《信息网络传播权保护条例》,如我们转载的作品侵犯了您的权利,请您通知我们,请将本侵权页面网址发送邮件到qingge@88.com,深感抱歉,我们会做删除处理。

目录[+]