function - 如何将任意数据类型写入Matlab元胞数组

标签 function matlab types return-value cell-array

这是一个一般性问题,与特定操作无关。我希望能够将任意函数的结果写入元胞数组的元素中,而不考虑函数返回的数据类型。考虑这个伪代码:

zout = cell(n,m);
myfunc = str2func('inputname'); %assume myfunc puts out m values to match zout dimensions
zout(1,:) = myfunc(x,y);

例如,这适用于 "inputname"== "strcat",假设 xy 是具有适当维度的字符串或字符串单元格。但如果“inputname”==“strcmp”则输出是一个逻辑数组,Matlab 会抛出错误。我需要做

zout(1,:) = num2cell(strcmp(x,y));

所以我的问题是:有没有一种方法可以填充元胞数组 zout 而不必测试 myfunc(x,y 生成的变量的类型?我首先使用 struct (如果是这样,填充它的最佳方法是什么)?
(我通常是 R 用户,我可以轻松使用 list 变量)

编辑:为了简化总体范围,请添加以下“要求”: 现在我们假设,对于返回多个输出的函数,仅需要在 zout 中捕获第一个输出。但是,当此输出是 N 个值的向量或单元向量(即 Nx1 单元数组)时,这些 N 值将映射到 zout(1,1:N)

最佳答案

So my question is: is there a way to fill the cell array zout without having to test for the type of variable generated by myfunc(x,y) ? Should I be using a struct in the first place (and if so, what's the best way to populate it)?

@NotBoStyf 提供的答案已经差不多了,但还不完全是。单元阵列是正确的选择。然而,答案很大程度上取决于函数的输出数量。

只有一个输出的函数

函数strcmp只有一个输出,即数组。原因是

zout{1,:} = strcmp(x,y)

给您一条错误消息,当 zout 的尺寸为 N x 2 时,左侧 ( zout{1,:} ) 期望来自右侧的两个输出。您可以通过以下方式解决此问题:

[zout{1,:}] = num2cell(strcmp(x,y));  % notice the square brackets on the LHS

但是,确实没有理由这样做。您可以简单地定义 zout作为 N x 1 元胞数组并捕获结果:

zout = cell(1,1);

x = 'a';
y = { 'a', 'b' };

zout{1} = strcmp(x,y);

% Referring to the results:
x_is_y_1 = zout{1}(1);
x_is_y_2 = zout{1}(2);

还有一种情况需要考虑...

具有多个输出的函数

如果您的函数产生多个输出(而不是一个数组输出),那么这只会捕获第一个输出。产生多个输出的函数定义如下:

function [outA,outB] = do_something( a, b )
  outA = a + 1;
  outB = b + 2;
end

在这里,您需要显式捕获两个输出参数。否则,您只会得到 a 。例如:

outA = do_something( [1,2,3], [4,5,6] ); % outA is [2,3,4]

[outA,outB] = do_something( [1,2,3], [4,5,6] ); % outA is [2,3,4], outB is [6,7,8]

Z1 = cell(1,1);
Z1{1,1} = do_something( [1,2,3], [4,5,6] ); % Z1{1,1} is [2,3,4]

Z2 = cell(1,2);
Z2{1,1:2} = do_something( [1,2,3], [4,5,6] ); % Same error as above.  
% NB: You really never want to have a cell expansion that is not surrounded 
% by square brackets.

% Do this instead:
[Z2{1,1:2}] = do_something( [1,2,3], [4,5,6] ); % Z2{1,1} is [2,3,4], Z2{1,2} is [6,7,8]

这也可以通过编程来完成,但有一些限制。假设我们被赋予了函数 func它接受一个输入并返回恒定(但未知)数量的输出。我们 有元胞数组inp包含我们想要处理的输入,我们想要收集 outp 周围的单元格中的结果:

N = numel(inp);
M = nargout(@func);  % number of outputs produced by func 
outp = cell(N,M);
for i=1:N
  [ outp{i,:} ] = func( inp{i} );
end

这种方法有一些注意事项:

  1. 它捕获所有输出。这并不总是您想要的。

  2. 捕获所有输出通常会改变函数的行为。例如,find如果仅使用一个输出,则函数返回线性索引;如果使用两个输出,则返回行/列索引;如果使用三个输出,则返回行/列/值。

  3. 它不适用于具有可变数量输出的函数。这些函数定义为 function [a,b,...,varargout] = func( ... )nargout如果函数有 varargout 将返回负数在其输出列表中声明,因为 Matlab 无法知道将产生多少个输出。

将数组和单元输出解压到单元中

All true so far, but: what I am hoping for is a generic solution. I can't use num2cell if the function produces cell outputs. So what worked for strcmp will fail for strcat and vice versa. Let's assume for now that, for a function which returns multiple outputs, only the first one need be captured in zout – Carl Witthoft

要为所有返回单元格或数组的函数提供统一的输出语法,请使用适配器函数。以下是处理数值数组和单元格的示例:

function [cellOut] = cellify(input)
  if iscell(input)
    cellOut = input;
  elseif isnumeric(input)
    cellOut = num2cell(input);
  else
    error('cellify currently does not support structs or objects');
  end
end

要将输出解包到二维元胞数组中,每个输出的大小必须是常量。假设M输出:

N = numel(inp);
% M is known and constant
outp = cell(N,M);
for i=1:N
  outp(i,:) = cellify( func( inp{i} ) );  % NB: parentheses instead of curlies on LHS
end

输出可以被寻址为 outp{i,j} 。另一种方法允许输出的大小发生变化:

N = numel(inp);
% M is not necessary here
outp = cell(N,1);
for i=1:N
  outp{i} = cellify( func( inp{i} ) );  % NB: back to curlies on LHS
end

输出可以被寻址为 outp{i}{j} ,并且输出的大小可能会有所不同。

需要记住的一些事情:

  1. Matlab 单元基本上是低效的指针。 JIT 编译器并不总是像优化数值数组那样优化它们。

  2. 将数值数组拆分为单元格可能会消耗大量内存。每个分割值实际上是一个数值数组,它具有与其关联的大小和类型信息。在数字数组形式中,每个数组都会发生一次。当数组被分割时,每个元素都会发生一次。

关于function - 如何将任意数据类型写入Matlab元胞数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11209158/

相关文章:

typescript - 为什么 typescript 在实现抽象函数时忽略严格的空检查?

security - 如果从外部来源获取字符串以外的其他数据类型是否可能有害?

javascript - 在 Javascript/Jquery 中删除 URL 的最后部分

linux - bash 。可变的可见性和生命周期

java - 调度时间表算法

math - 使用 MATLAB 的二阶非线性微分方程

testing - 使用 Haskell 的类型替换其他语言的 assert 语句或 if 检查

php - 有用函数的集合最好作为函数库保存还是应该转换为类?

mysql - 更改 MySQL 字符串列中的 h 标签

matlab - MATLAB 中的 Canny 边缘检测器