9
$\begingroup$

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}}}?

$\endgroup$
1
  • $\begingroup$ {{x -> a}, {x -> b}, {x -> c, x -> d}} /. (x_ -> a_) :> {x, a} /. {{a__}} :> {a} also works. $\endgroup$ Commented Feb 16, 2020 at 13:58

4 Answers 4

14
$\begingroup$

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:

$\endgroup$
2
  • $\begingroup$ Is it possible to use Apply to 2nd levelspec? $\endgroup$
    – kile
    Commented Feb 17, 2020 at 9:51
  • 1
    $\begingroup$ @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. $\endgroup$
    – Mr.Wizard
    Commented Feb 17, 2020 at 11:55
4
$\begingroup$

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.

$\endgroup$
2
$\begingroup$
rules = {{x -> a}, {x -> b}, {x -> c, x -> d}};

rules /. x : {_Rule, __} :> List @@@ x /. Rule :> Splice @* List

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

$\endgroup$
2
$\begingroup$
rules = {{x -> a}, {x -> b}, {x -> c, x -> d}};

Using Delete:

f = Function[s, If[Length@s == 1, List@Delete[First@s, 0], 
    Map[List@*Delete[0]]@s]];

f /@ rules

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

$\endgroup$

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