define open generic trim
(sequence :: <sequence>, to-remove :: <object>, #key from)
=> (sequence :: <sequence>);
define method trim
(sequence :: <sequence>, to-remove :: <object>, #key from = #"both")
=> (sequence :: <sequence>)
trim(sequence, curry(\=, to-remove), from: from)
end;
define method trim
(sequence :: <sequence>, remove? :: <function>, #key from = #"both")
=> (sequence :: <sequence>)
let start-index :: <integer> = 0;
let end-index :: <integer> = sequence.size;
if (member?(from, #[left:, both:]))
while (start-index < end-index & remove?(sequence[start-index]))
start-index := start-index + 1;
end;
end;
if (member?(from, #[right:, both:]))
while (end-index > start-index & remove?(sequence[end-index - 1]))
end-index := end-index - 1;
end;
end;
if (start-index = 0 & end-index = sequence.size)
sequence
else
copy-sequence(sequence, start: start-index, end: end-index)
end
end method trim;
define method trim
(sequence :: <sequence>, to-remove :: <collection>, #key from = #"both")
=> (sequence :: <sequence>)
trim(sequence, rcurry(member?, to-remove), from: from)
end;
define method trim
(sequence :: <sequence>, remove? :: <function>, #key from = #"both")
=> (sequence :: <sequence>)
let keep? = complement(remove?);
let start-index = member?(from, #[left:, both:]) & find-key(sequence, keep?);
let end-index = member?(from, #[right:, both:]) & find-last-key(sequence, keep?);
let end-index = if (end-index) end-index + 1 end; // Still #f if end-index is #f.
if (~start-index & ~end-index)
sequence
else
copy-sequence(sequence, start: start-index | 0, end: end-index | sequence.size)
end
end method trim;define method trim
(sequence :: <sequence>, remove? :: <function>, #key from = #"both")
=> (sequence :: <sequence>)
let keep? = complement(remove?);
let start-index = member?(from, #[left:, both:]) & find-key(sequence, keep?);
let end-index = member?(from, #[right:, both:]) & find-last-key(sequence, keep?);
if (~start-index & ~end-index)
sequence
else
copy-sequence(sequence, start: start-index | 0, end: end-index | sequence.size)
end
end method trim;// If there were a version of find-key that used backwards-iteration-protocol called find-last-key,
// we could implement the main trim function like so. Presumably, iteration using find-key and
// find-last-key would be most optimized for the specific data structure being trimmed, rather than
// using explicit indexing.
define method trim
(sequence :: <sequence>, remove? :: <function>, #key from = #"both")
=> (sequence :: <sequence>)
let keep? = complement(remove?);
let start-index =
if (member?(from, #[left:, both:]))
find-key(sequence, keep?, failure: 0)
else
0
end if;
let end-index =
if (member?(from, #[right:, both:]))
find-last-key(sequence, keep?, failure: sequence.size - 1)
else
sequence.size - 1
end if;
if (start-index = 0 & end-index = sequence.size)
sequence
else
copy-sequence(sequence, start: start-index, end: end-index)
end
end method trim;