Skip to content

Commit

Permalink
fix x(ix) = [] element deletion for string, table, datetime, and ot…
Browse files Browse the repository at this point in the history
…her classes
  • Loading branch information
apjanke committed Feb 4, 2024
1 parent bf1db6c commit 95a4ff4
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 19 deletions.
10 changes: 10 additions & 0 deletions inst/calendarDuration.m
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,16 @@ function disp (this)

function this = subsasgnParensPlanar (this, s, rhs)
#SUBSASGNPARENSPLANAR ()-assignment for planar object
if (isnumeric (rhs) && isequal (size (rhs), [0 0]))
# Special `x(ix) = []` deletion form
this.Sign(s.subs{:}) = [];
this.Years(s.subs{:}) = [];
this.Months(s.subs{:}) = [];
this.Days(s.subs{:}) = [];
this.Time(s.subs{:}) = [];
this.IsNaN(s.subs{:}) = [];
return
endif
if (! isa (rhs, 'calendarDuration'))
rhs = calendarDuration (rhs);
endif
Expand Down
6 changes: 6 additions & 0 deletions inst/categorical.m
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,12 @@ function summary (this)

function this = subsasgnParensPlanar (this, s, rhs)
#SUBSASGNPARENSPLANAR ()-assignment for planar object
if (isnumeric (rhs) && isequal (size (rhs), [0 0]))
# Special `x(ix) = []` deletion form
this.code(s.subs{:}) = [];
this.tfMissing(s.subs{:}) = [];
return
endif
if (! isa (rhs, 'categorical'))
# TODO: This conversion is probably wrong. It probably needs to be done
# with respect to this's existing cats list
Expand Down
6 changes: 6 additions & 0 deletions inst/datetime.m
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,12 @@ function disp (this)

function out = subsasgnParensPlanar (this, s, rhs)
#SUBSASGNPARENSPLANAR ()-assignment for planar object
if (isnumeric (rhs) && isequal (size (rhs), [0 0]))
# Special `x(ix) = []` deletion form
out = this;
out.dnums(s.subs{:}) = [];
return
endif
if (! isa (rhs, 'datetime'))
rhs = datetime (rhs);
endif
Expand Down
7 changes: 7 additions & 0 deletions inst/duration.m
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,13 @@ function disp (this)

function out = subsasgnParensPlanar (this, s, rhs)
#SUBSASGNPARENSPLANAR ()-assignment for planar object
if (isnumeric (rhs) && isequal (size (rhs), [0 0]))
# Special `x(ix) = []` deletion form
out = this;
out.days = [];
out.days(s.subs{:}) = [];
return
endif
if (! isa (rhs, 'duration'))
rhs = duration (rhs);
endif
Expand Down
6 changes: 6 additions & 0 deletions inst/string.m
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,12 @@ function disp (this)

function this = subsasgnParensPlanar (this, s, rhs)
#SUBSASGNPARENSPLANAR ()-assignment for planar object
if (isnumeric (rhs) && isequal (size (rhs), [0 0]))
# Special `x(ix) = []` deletion form
this.strs(s.subs{:}) = [];
this.tfMissing(s.subs{:}) = [];
return
endif
if (! isa (rhs, 'string'))
rhs = string (rhs);
endif
Expand Down
81 changes: 62 additions & 19 deletions inst/table.m
Original file line number Diff line number Diff line change
Expand Up @@ -987,15 +987,27 @@ function prettyprint (this)
endif

out = this;
switch (s(1).type)
switch (s.type)
case '()'
error ('table.subsasgn: Assignment using ()-indexing is not supported for table');
if (isnumeric (rhs) && isequal (size (rhs), [0 0]))
# Special `x(ix) = []` deletion form
if (numel (s.subs) != 2)
error ('table.subsasgn: table subscripting must use exactly 2 subscripts; got %d subscripts', ...
numel (s.subs))
endif
if (! isequal (s.subs{2}, ":"))
error ('table.subsasgn: in `tbl(ixR,ixC) = []`, ixC must be ":"')
endif
out = subsetrows_impl(this, s.subs{1}, true);
else
error ('table.subsasgn: Assignment using ()-indexing is not yet implemented for table');
end
case '{}'
if (numel (s.subs) != 2)
error ('table.subsasgn: {}-indexing of table requires exactly two arguments');
endif
[ixRow, ixVar] = resolveRowVarRefs (this, s.subs{1}, s.subs{2});
if(! isscalar (ixVar))
if (! isscalar (ixVar))
error ('table.subsasgn: {}-indexing must reference a single variable; got %d', ...
numel (ixVar));
endif
Expand All @@ -1009,6 +1021,8 @@ function prettyprint (this)
endif
if (isequal (s.subs, 'Properties'))
# Special case for this.Properties access
# Will need to be implemented using chained assignment, and probably handled
# up above in a special case near the top.
error ('table.subsasgn: .Properties access is not implemented yet');
else
out = setvar (this, s.subs, rhs);
Expand Down Expand Up @@ -3314,22 +3328,7 @@ function prettyprint (this)
##
## @end deftypefn
function out = subsetrows (this, ixRows)
out = this;
if (! isnumeric (ixRows) && !islogical (ixRows))
# TODO: Hmm. Maybe we ought not to do this check, but just defer to the
# individual variable values' indexing logic, so SUBSREF/SUBSINDX overrides
# are respected. Would produce worse error messages, but be more "right"
# type-wise.
error ('table.subsetrows: ixRows must be numeric or logical; got a %s', ...
class (ixRows));
endif
s = struct ('type', '()', 'subs', {{ixRows,':'}});
for i = 1:width (this)
out.VariableValues{i} = subsref (out.VariableValues{i}, s);
endfor
if (! isempty (this.RowNames))
out.RowNames = out.RowNames(ixRows);
endif
out = subsetrows_impl (this, ixRows);
endfunction

## -*- texinfo -*-
Expand Down Expand Up @@ -3480,6 +3479,50 @@ function mustBeAllColVectorVars (this)

methods (Access = private)

function out = subsetrows_impl (this, ixRows, doInvertIx)
# Internal implementation for subsetrows and restrict, supporting index inversion
if (nargin < 3 || isempty (doInvertIx)); doInvertIx = false; end
mustBeScalarLogical (doInvertIx);

ixRowsIn = ixRows;
if (doInvertIx)
if (islogical (ixRowsIn))
ixRows = ! ixRowsIn;
elseif (isnumeric (ixRowsIn))
nRows = height (this);
tfBad = ixRows > nRows;
if any (tfBad)
badIxs = ixRows(tfBad);
error ('table: invalid row index: index (%d) exceeds number of rows (%d)', ...
badIxs(1), nRows)
endif
ixRows = 1:height (this);
ixRows(ixRowsIn) = [];
else
error ('table: invalid type for ixRows: must be logical or numeric; got %s', class (ixRows))
endif
endif

out = this;
if (! isnumeric (ixRows) && !islogical (ixRows))
# TODO: Hmm. Maybe we ought not to do this check, but just defer to the
# individual variable values' indexing logic, so SUBSREF/SUBSINDX overrides
# are respected. Would produce worse error messages, but be more "right"
# type-wise.
error ('table.subsetrows: ixRows must be numeric or logical; got a %s', ...
class (ixRows));
endif
s = struct ('type', '()', 'subs', {{ixRows,':'}});
varVals = this.VariableValues;
for i = 1:width (this)
varVals{i} = subsref (varVals{i}, s);
endfor
out.VariableValues = varVals;
if (! isempty (this.RowNames))
out.RowNames = out.RowNames(ixRows);
endif
endfunction

function out = proxykeysForOneTable (this)
varProxyKeys = cell (size (this.VariableNames));
for iVar = 1:numel (this.VariableNames);
Expand Down

0 comments on commit 95a4ff4

Please sign in to comment.