Code covered by the BSD License  

Highlights from
Cell Array Mimic

Cell Array Mimic

by

 

03 Jun 2010 (Updated )

This is a class which mimics a cell array by implementing several cell array functions.

CAindex
%% CAindex mimics a cell array
% Written by Will Jackson
% Copyright 2010 The MathWorks, Inc.

classdef CAindex
    
    properties
        CA
    end
    
    methods
        
        function obj = CAindex(cellarray)
            if nargin > 0
                obj.CA = cellarray;
            end
        end
        
        function obj = set.CA(obj, value)
            if iscell(value) || isempty(value)
                obj.CA = value;
            else
                error('Unable to assign value to cell array');
            end
        end
        
        function varargout = subsref(obj,s)
            switch s(1).type
                
                % Use the built-in subsref for dot notation on a cell
                % array, except when setting or getting the CA property
                case '.'
                    nargout
                    %varargout = cell(1,nargout(@()builtin('subsref',obj,s)));
                    varargout{:} = builtin('subsref',obj,s);
                    
                %Use built-in subsref unless a string is given.  Then,
                %search for that string in the first row and return the
                %data beneath it as a cell array
                case '()'
                    if ischar(s.subs{1})
                        i = strmatch(s.subs, obj.CA(1,:));
                        if ~isempty(i)
                            varargout = cell(numel(obj.CA(2:end,i)),1);
                            varargout(:) = {obj.CA(2:end,i)};
                            return
                        end
                    end
                    varargout{:}  = subsref(obj.CA,s);
                    varargout{:}  = subsref(obj.CA,s);
                    
                %Use built-in subsref unless a string is given.  Then,
                %search for that string in the first row and return the
                %data beneath it as a comma separated list
                case '{}'
                    if ischar(s.subs{1})
                        i = strmatch(s.subs{1}, obj.CA(1,:));
                        if ~isempty(i)
                            varargout = cell(numel(obj.CA(2:end,i)),1);
                            [varargout{:}] = obj.CA{2:end,i};
                            return
                        end
                    end
                    varargout = cell(numel(obj,s.subs{:}),1);
                    [varargout{:}] = subsref(obj.CA,s);
            end
        end
        
        function obj  = subsasgn(obj,s,val)
            if isempty(s) && iscell(val)
                obj.CA = val;
            end
            
            switch s(1).type
                
                % Use the built-in subsref for dot notation on a cell
                % array, except when setting or getting the CA property
                case '.'
                    if strcmp(s.subs,'CA') && iscell(val);
                        obj.CA = val;
                    else
                        obj.CA = subsasgn(obj.CA,s,val);
                    end
                    
                %Use built-in subsasgn unless a string is given.  Then,
                %search for that string in the first row and set the
                %data beneath it with val
                case '()'   
                    if isnumeric(val)
                        val = num2cell(val);
                    end
                    
                    if isequal(val,[]) || isequal(val,{})
                        val = {[]};
                    end
                    
                    %If given a string, look for it in first row
                    if ischar(s.subs{1}) && ~isequal(s.subs{1},':') && ~isequal(s.subs{1},'end')
                        i = [];
                        if ~isempty(obj.CA)
                            i = strmatch(s.subs{1}, obj.CA(1,:));
                        end
                        
                        % If string not found, create new row
                        if isempty(i)
                            i = builtin('end',obj.CA,2,2) + 1;
                            obj.CA{1,i} = s.subs{1};
                        end
                        maxindex = length(val(:)) + 1;
                        obj.CA(2:maxindex,i) = val(:);
                        
                        % Nullify old values in column
                        if(maxindex < numel(obj.CA(2:end,end)))
                            obj.CA(maxindex+1:numel(obj.CA(:,i)),i) = ...
                                cell(numel(obj.CA(:,i))- maxindex, 1);
                        end 
                        obj.CA = removeemptyrows(obj.CA);
                        return
                    end
                    obj.CA = subsasgn(obj.CA,s,val);
                    obj.CA = removeemptyrows(obj.CA);

                    
                %Use built-in subsasgn unless a string is given.  Then,
                %search for that string in the first row and set the
                %data beneath it to val
                case '{}'
                    % Without an array or cell (array) or for NULL, simply
                    % use the default subasgn
                    if ~(isnumeric(val) || iscell(val)) || isempty(val)
                        obj.CA = subsasgn(obj.CA,s,val);
                        return
                    end
                    s(1).type = '()';
                    obj = subsasgn(obj,s,val);
            end
        end
        
        function obj = vertcat(varargin)
            a = CAindex(cell(size(varargin(:))));
            for i = 1:length(varargin(:))
                a(i) = varargin{i};
            end
            
            obj = CAindex(vertcat(a.CA));
        end
        
        function obj = horzcat(varargin)
            a = CAindex(cell(size(varargin(:))));
            for i = 1:length(varargin(:))
                a(i) = varargin{i};
            end
            
            obj = CAindex(horzcat(a.CA));
        end
        
        function n = numel(obj, varargin)
            if nargin == 1 && isa(obj, 'CAindex')
                % This is so that plot and disp can work with obj.plot
                % syntax (otherwise it would be called for each element)
                n = 1;      
                return
            elseif ischar(varargin{1})
                i = strmatch(varargin{1}, obj.CA(1,:));
                if ~isempty(i)
                    n = length(obj.CA(2:end,1));
                    return
                end
            end
            n = builtin('numel', obj.CA, varargin{:});
        end
        
        function ind = end(obj,k,n)
            ind = builtin('end',obj.CA,k,n);
        end
        
        function obj = transpose(obj)
            obj.CA = (obj.CA).';
        end
        
        function obj = ctranspose(obj)
            obj.CA = (obj.CA)';
        end
        
        function s = size(obj)
            s = size(obj.CA);
        end
        
        function disp(varargin)
            for i = 1:length(varargin)
                disp([varargin{i}.CA]);
            end
        end
  
        function plot(obj)
            % Convert empty cells to NaN's for plotting
            newcell = cellfun(@toNaN, obj.CA(2:end,:), 'UniformOutput', false);
            % Convert cell array to matrix
            m = cell2mat(newcell);
            plot(m);
            legend(obj.CA(1,:))
        end
    end
end

function CA = removeemptyrows(CA)
    for j = size(CA,1):-1:1
        if ~all(cellfun(@isempty,CA(j,:)))
            CA = CA(1:j,:);
            break;
        end
    end
end
        
function varargout = toNaN(varargin)
    if(isempty(varargin{:}))
        varargout{:} = NaN;
    else 
        varargout = varargin;
    end
end

Contact us