필터 지우기
필터 지우기

overloading subsref

조회 수: 7 (최근 30일)
Daniel Shub
Daniel Shub 2011년 5월 4일
How do you support colon notation in an overloaded subsref? I am trying to overload subsref for a class I am writing. I have an object obj with property prop. I want obj.prop(n, m) to call a method obj.calcprop(n, m). For simplicity, assume calcprop returns obj.x(n, m) (where x is another property). I cannot get calcprop to return the correct size output with colon notation: obj.prop(:). My subsref knows what the maximum values of n and m, nMax and mMax and I can use this to handle colon notation when nMax is greater than 1. For example,
nMax = 2; mMax = 10;
x = rand(nMax, mMax);
isequal(size(x(:)), size(x((1:(nMax*mMax))')))
If I call obj.calcprop((1:(nMax*mMax))', []) and handle the empty argument in a special way. The problem is that nMax = 1; mMax = 10; x = rand(nMax, mMax); isequal(size(x(:)), size(x((1:(nMax*mMax))'))) doesn't work. These also do not work:
isequal(size(x(:)), size(x(1:(nMax*mMax))))
isequal(size(x(:)), size(x(1, 1:mMax)))
isequal(size(x(:)), size(x(1, (1:mMax)')))
Do I just take the "wrong" size output of calcprop and deal with it in my overloaded subsref?

답변 (2개)

Malcolm Lidierth
Malcolm Lidierth 2011년 9월 28일
Daniel Is this any use? It is called from subsref in some of my own custom objects and converts from substruct to subs:
function [subs, index]=struct2sub(siz, index)
% struct2sub returns the subscripts from a substruct structure
% Examples:
% subs=struct2sub(siz, index);
% [subs, index]=struct2sub(siz, index);
%
% For a matrix M, struct2sub returns the subscripts
% subs=struct2sub(siz, index);
% where siz=size(M) and index is a substruct object (as used by
% subsref or subsasgn methods)
% M may be a field of a structure or object referenced through
% index
%
% The output subs is a cell array of subscripts suitable for use
% with the standard MATLAB indexing and sub-referencing functions.
%
% If required, the output index is a copy of the input index
% with the subs field of the last element fully expanded
% numerically (i.e. all ':' are replaced with the appropriate
% vectors)
%
% Generate linear indices from the result using the standard MATLAB sub2ind
% function:
% subs=struct2sub(siz, index);
% ind=sub2ind(siz, subs{:});
n=numel(index(end).subs);
for k=1:n
% Deal with non-numeric subscripts
if ischar(index(end).subs{k})
% ':' is the only possibility
index(end).subs{k}=1:siz(k);
end
end
subs=cell(1,n);
if all(cellfun(@numel, index(end).subs)==1)
% All scalar entries
[subs{:}]=index(end).subs{:};
else
subs=cell(1,numel(index(end).subs));
[subs{:}]=ndgrid(index(end).subs{:});
for k=1:numel(subs)
subs{k}=subs{k}(:).';
end
end
return
end

Ulrik
Ulrik 2011년 10월 20일
Thanks for the code... I rewrote it bit. e.g did not work with index (true/false), an empty s.subs e.g. you can do this in matlab:
a = [];
a()
Info: Please note that cell's are not supported "{}" in my version
-------------------------------------
function [sub,s] = struct2sub(siz, s)
% Initial check of input s
if numel(s) == 2 && strcmp(s(1).type,'.') && ischar(s(1).subs) && strcmp(s(2).type,'()'),
s(1) = [];
elseif ~(numel(s) == 1 && strcmp(s(1).type,'()')),
error('struct2sub:InvalidStructure','Input error: Structure of s is not supported');
end;
% Preforms ajustment of the input variable siz
if length(siz) ~= numel(s.subs),
%Adjust input
if ~numel(s.subs),
s.subs = cell(size(siz));
s.subs(:) = {':'};
elseif length(siz) < numel(s.subs)
%Adjust for trailing singleton dimensions
siz = [siz ones(1,numel(s.subs)-length(siz))];
else
%Adjust for linear indexing on last element
siz = [siz(1:numel(s.subs)-1) prod(siz(numel(s.subs):end))];
end
end
for sCount = 1:numel(s.subs)
if ischar(s.subs{sCount}) && strcmp(strtrim(s.subs{sCount}),':'),
s(end).subs{sCount} = 1:siz(sCount);
elseif islogical(s.subs{sCount})
if numel(s.subs{sCount}) ~= siz(iCount),
error('struct2sub:InvalidStructureSubsSize','Input error: s.subs of wrong size');
end;
s(end).subs{sCount} = find(s(end).subs{sCount});
end;
end;
[sub{1:numel(s.subs)}] = ndgrid(s.subs{:},1);
for sCount = 1:numel(sub),
sub{sCount} = sub{sCount}(:)';
end;
  댓글 수: 1
Malcolm Lidierth
Malcolm Lidierth 2011년 10월 23일
@Ulrik
Glad it was of some use. Note that calling ndgrid is not a good general solution. It can be slow and the output will generally take more memory than the data you are trying to access.
struct2sub was designed to be called from a subsref method - not to replace it. In my code it is only called when more efficient methods are not available and the subsref takes care of e.g. logical indices, '()' etc, missing dims etc.

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

카테고리

Help CenterFile Exchange에서 Matrices and Arrays에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by