When I use cellfun with an empty cell as input, the output is an empty array. Is that a bug in matlab? How can that be avoided?
If i do x = arrayfun(@(i){y(i)},t),
and t is not an empty array, then x is a cell array and if t is empty, then x is an empty array which i can understand.
but if i do x = cellfun(@(i)y(i),num2cell(t)), i would expect x to be a cell always. no matter what t is.
Is it possible to always have x a cell array without checking if it is empty?

 채택된 답변

Guillaume
Guillaume 2015년 1월 7일

0 개 추천

x = cellfun(@fn, c)
x = arrayfun(@fn, a)
x will never be a cell array regardless of input cell array c or array a, unless function fn returns a cell array. Thus with,
x = cellfun(@(i) y(i), num2cell(t))
unless y(i) is a cell array, x will never be a cell array.
To force cellfun and arrayfun to return cell arrays, set 'UniformOutput' to false:
x = cellfun(@(i) y(i), num2cell(t), 'UniformOutput', false)

댓글 수: 5

Wesley Ooms
Wesley Ooms 2015년 1월 7일
편집: Wesley Ooms 2015년 1월 7일
Yes, but with the curly brackets in @fn, i force the output to be a cell as an example:
n = 2:1 ;
x = 1:10 ;
fun = @(i){x(i)} ;
y = fun(n) ; % this returns a cell with an empty matrix, while
y = arrayfun(@(i){x(i)},n) ; % returns an empty matrix.
The question is this; if i did
y = {1:numel(n)} ; % initialize y
for i=y{:}
y{i}=x(i);
end
how can i rewrite this with arrayfun or cellfun to remove the for loop without changing its behavior in case n is an empty array
Adam
Adam 2015년 1월 7일
In your example neither the for loop nor the arrayfun would do anything so the only reason your for loop example gives what you want is your 'initialise y' line. The for loop does nothing on an empty array and neither does the arrayfun.
The 'UniformOutput', false approach does give an empty cell array though as expected, it is just a different kind of emptiness than what you get with your y = fun(n) line and one that, in most cases, I would think to be more desirable.
An empty input should ideally give an empty output rather than a 1x1 cell as you appear to want.
Wesley Ooms
Wesley Ooms 2015년 1월 7일
Yes. I agree that the for loop does nothing. But the arrayfun actually does. If i initialize y to be a cell, the arrayfun changes the cell into an array. In my case this is not desitrable because further in the code, only cells for y are accepted so i have to do another isnumeric/isempty check. Therefore the 'UniformOutput' does not solve the problem.
Well to be perfectly equivalent to arrayfun, your for loop should be something like:
%y = arrayfun(@fn, x);
y = zeros(size(x));
for i = 1:numel(x)
tmp = fn(x(i));
if i == 1 && iscell(tmp)
y = cell(size(x));
end
y(i) = tmp;
end
Both behave the same way when passed an empty array.
The behaviour makes sense in any way. By default, arrayfun returns plain arrays and only returns cell arrays if explicitly asked or if the function called returned a cell array. When passed an empty array, arrayfun has no way to know that the function it never calls would return a cell array.
More practically, what are you actually trying to do? The examples that you've shown so far don't actually need any kind of arrayfun / cellfun. num2cell would be enough.
I also don't see why 'UniformOutput', false does not solve the problem.
Wesley Ooms
Wesley Ooms 2015년 1월 7일
편집: Wesley Ooms 2015년 1월 7일
Yes you are right that the code doesn't do much, but that is because i stripped all the functional code to isolate the problem. Now i also see that, as you mentioned, the arrayfun has no way to know that the function it never calls would return a cell array if it would have been called. So now instead of forcing t to be a cell, i was able to easily handle noncells if empty. That solved the problem. Thank you for your help.

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

도움말 센터File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

제품

질문:

2015년 1월 7일

편집:

2015년 1월 7일

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by