1. Problem statement
Going from right to left, I want do delete all elements after they have occured n
times. The solution I found seems to work reliably, but is rather long and uses a function, DeleteElements
, which was only introduced in V 13.1
.
2. Current solution
DeleteAbove[lis_, n_] /; n >= Max @ Counts @ lis := {}
DeleteAbove[lis_, n_] :=
Module[{tal, del},
tal = Select[Tally @ lis, Last[#] > n &];
del = Rule @@ ReplaceAll[{a_, b_} :> {a - n, b}] @ Reverse @ Transpose @ tal;
Reverse @ DeleteElements[Reverse @ lis, del]]
3. Examples
list = {1, 5, 5, 2, 2, 6, 4, 2, 2, 5, 8, 8, 5, 5};
DeleteAbove[list, 3]
{1, 5, 5, 2, 2, 6, 4, 2, 5, 8, 8}
DeleteAbove[{2, 2, 1, 1, 1, 8, 1}, 2]
{2, 2, 1, 1, 8}
4. Questions
- How would a nicer / shorter solution look like?
- Can this problem be solved with one of the
Sequence
- functions?
DeleteAbove[{8,8},3]
give the empty set? $\endgroup$Max@ Counts@lis
you get many failure messages . Therefore the first definition ofDeleteAbove
. One could replace the empty set with a message like ' n exceeds maximum element count'. $\endgroup$8
only occurs twice in the list, and you want to delete above3
occurrences, surely the output should be{8,8}
? $\endgroup$DeleteAbove[{8, 8}, 3]
should give{8,8}
and not a bunch of error messages or the empty set. $\endgroup$DeleteAbove[lis_, n_] /; n >= Max @ Counts @ lis := lis
. I.e. just return the list and do nothing (the identity operation) $\endgroup$