11
$\begingroup$

Given list = {1, 2, f[3, 4], {5, {6, g[7, h[8, 9]]}}, {f[10], 11}};

I want to get {f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}

just delete a single integer and need to keep the structure, use DeleteCases but get this result

DeleteCases[list, _Integer, All, Heads -> False]

{f[], {{g[h[]]}}, {f[]}}

Am I using it wrong, should I use a more suitable function?

$\endgroup$

7 Answers 7

11
$\begingroup$
list /. {expr : (f | g | h)[__] :> expr, _Integer -> Nothing}
(* {f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}} *)
$\endgroup$
1
  • 3
    $\begingroup$ A slight variation: list/.{_Integer:>Nothing,x:_f | _g | _h :> x} (and +1, of course) $\endgroup$
    – user1066
    Commented Apr 10, 2023 at 18:31
12
$\begingroup$

You could use DeleteCases on each List:

MapAt[DeleteCases[_Integer], list, Drop[Position[list, List], 0, -1]]
{f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}
$\endgroup$
11
$\begingroup$

I might think of this as transforming each list into a special type of list that automatically deletes any non-atomic elements given to it.

list /. List -> Function[Null, Select[{##}, Not@*AtomQ]]

I generalized this to atoms instead of just integers, because that's what I "read between the lines" of your question. But of course you could stick with integers.

list /. List -> Function[Null, Select[{##}, Not@*IntegerQ]]

or

list /. List -> Function[Null, DeleteCases[{##}, _Integer]]
$\endgroup$
10
$\begingroup$
list //. {OrderlessPatternSequence[__Integer, keep : (_@__) ..]} :> {keep}
{f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}

And a variation on @xzczd's method:

list /. {keep : Except[List]@__ :> keep, _Integer -> Nothing}
{f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}
$\endgroup$
1
  • 4
    $\begingroup$ Just keep___ works for the first (and three underscores/dots are needed if it's possible to empty a list) $\endgroup$
    – att
    Commented Apr 11, 2023 at 7:36
7
$\begingroup$

Another way to do this using SubsetReplace, Internal-CopyListStructure and ReplaceAll:

Internal`CopyListStructure[list, 
SubsetReplace[Flatten@list, {_Integer} -> s]] /. s -> Nothing

(*{f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}*)

Or the equivalent form:

F = Activate@
Internal`CopyListStructure[#, 
SubsetReplace[Flatten@#, {_Integer} -> Inactive[Nothing]]] &;

F@list

(*{f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}*)

A generalization of @xzczd's answer is to find the heads of expressions that we don't want to remove using Cases as follows:

patt = Alternatives @@ Blank /@ Union@Cases[#, 
       s : Except[_List | _Integer] :> Head[s], {0, ∞}] &@list

(*_f | _g | _h*)

list /. {_Integer :> Nothing, s : patt :> s}

(*{f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}*)

Another way, using Cases and DeleteCases:

exc = Cases[#, s : Except[_List | _Integer] :> s, {0, ∞}] &;

DeleteCases[#, Alternatives @@ Complement[Flatten@#, exc@#], Depth@#] &@list

(*{f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}*)
$\endgroup$
6
$\begingroup$

I can't tell if this is clever or just silly, but it's a variation on the theme:

In[22]:= noIntegers[bef___, __Integer, aft___] := noIntegers[bef, aft];
In[23]:= list /. List -> noIntegers /. noIntegers -> List

Out[23]= {f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}
$\endgroup$
1
$\begingroup$
list = {1, 2, f[3, 4], {5, {6, g[7, h[8, 9]]}}, {f[10], 11}};

A variant of E. Chan-López solution:

p = Union @ Cases[list, a_[__] /; a =!= List :> a, -1] /. 
 x_ :> Alternatives @@ Thread[_x]

_f | _g | _h

list /. {s : p :> s, _Integer :> Nothing}

{f[3, 4], {{g[7, h[8, 9]]}}, {f[10]}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.