6

Here is what I have done.

Input

DeleteCases[{{x -> a}, {x -> b}, {x -> c, x -> d}}, Rule, {2}]

Output

{{x -> a}, {x -> b}, {x -> c, x -> d}}

Why is it not {{x, a}, {x, b}, {{x, c}, {x, d}}}?

kile
  • 1,671
  • 5
  • 10

2 Answers2

12

DeleteCases does not by default operate on heads. You can set the Heads option to True to change that.

DeleteCases[{{x -> a}, {x -> b}, {x -> c, x -> d}}, Rule, {3}, Heads -> True]
{{x, a}, {x, b}, {x, c, x, d}}

Note that the last term has become {x, c, x, d} which is not quite what you expected, but it is logically consistent if we expect {x -> a} to become {x, a}.

A simpler path to the same output in this case is:

{{x -> a}, {x -> b}, {x -> c, x -> d}} /. Rule -> Sequence
{{x, a}, {x, b}, {x, c, x, d}}

Your expected output can be had from:

{{x -> a}, {x -> b}, {x -> c, x -> d}} /. Rule -> List /. {x_List} :> x
{{x, a}, {x, b}, {{x, c}, {x, d}}}

Recommended reading:

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Is it possible to use Apply to 2nd levelspec? – kile Feb 17 '20 at 09:51
  • 1
    @kile Yes! You could write Apply[Sequence, {{x -> a}, {x -> b}, {x -> c, x -> d}}, {2}] But understand that Sequence must evaluate, so this is not directly deleting the head. See the "Recommended reading" link for details. – Mr.Wizard Feb 17 '20 at 11:55
2

Replacing heads is generically supported by Apply (@@ / @@@). So a functional way may look like this:

rules = {{x -> a}, {x -> b}, {x -> c, x -> d}};
If[Length[#] == 1, Flatten[#], Identity[#]] & /@ Apply[List, rules, {-2}]
{{x, a}, {x, b}, {{x, c}, {x, d}}}

Or

If[Length[#] == 1, Sequence @@@ #, List @@@ #] & /@ rules

returns the same result.