Matlab's arrayfun for uniform output of class

2019-07-01 23:12发布

I need to build an array of objects of class ID using arrayfun:

% ID.m
classdef ID < handle
    properties
        id
    end
    methods
        function obj = ID(id)
            obj.id = id;
        end
    end
end

But get an error:

>> ids = 1:5;
>> s = arrayfun(@(id) ID(id), ids) 
??? Error using ==> arrayfun
ID output type is not currently implemented.

I can build it alternatively in a loop:

s = [];
for k = 1 : length(ids)
    s = cat(1, s, ID(ids(k)));
end

but what is wrong with this usage of arrayfun?

Edit (clarification of the question): The question is not how to workaround the problem (there are several solutions), but why the simple syntax s = arrayfun(@(id) ID(id), ids); doesn't work. Thanks.

标签: oop class matlab
3条回答
叼着烟拽天下
2楼-- · 2019-07-01 23:33

This is how I would create an array of objects:

s = ID.empty(0,5);
for i=5:-1:1
    s(i) = ID(i);
end

It is always a good idea to provide a "default constructor" with no arguments, or at least use default values:

classdef ID < handle
    properties
        id
    end
    methods
        function obj = ID(id)
            if nargin<1, id = 0; end
            obj.id = id;
        end
    end
end
查看更多
再贱就再见
3楼-- · 2019-07-01 23:48

You are asking arrayfun to do something it isn't built to do.

The output from arrayfun must be:

scalar values (numeric, logical, character, or structure) or cell arrays.

Objects don't count as any of the scalar types, which is why the "workarounds" all involve using a cell array as the output. One thing to try is using cell2mat to convert the output to your desired form; it can be done in one line. (I haven't tested it though.)

s = cell2mat(arrayfun(@(id) ID(id), ids,'UniformOutput',false));
查看更多
劫难
4楼-- · 2019-07-01 23:57

Perhaps the easiest is to use cellfun, or force arrayfun to return a cell array by setting the 'UniformOutput' option. Then you can convert this cell array to an array of obects (same as using cat above).

s = arrayfun(@(x) ID(x), ids, 'UniformOutput', false);
s = [s{:}];
查看更多
登录 后发表回答