19
$\begingroup$

I have a list:

{a, b, c, d, e, f, g, h, i, j} 

The goal is to get:

{a_, b_, c_, d_, e_, f_, g_, h_, i_, j_} 

I can replace one particular element by using:

{a, b, c, d, e, f, g, h, i, j} /. a -> a_

But my attemps to expand this approach to all elements doesn't work. What can I do?

$\endgroup$
  • 1
    $\begingroup$ {a, b, c, d, e, f, g, h, i, j} _ /. Times -> Pattern, which "accidentally" works since Times is Orderless and Blank[] happens to come after the variables. $\endgroup$ – Michael E2 Dec 17 '19 at 22:10
  • $\begingroup$ @MichaelE2 Sneaky... I like it! Actually I think you should put that in your answer; it's really fun. $\endgroup$ – Mr.Wizard Dec 17 '19 at 22:19
  • $\begingroup$ @Mr.Wizard OK, done. Thanks, $\endgroup$ – Michael E2 Dec 17 '19 at 22:27
  • $\begingroup$ Related: (121845) $\endgroup$ – Mr.Wizard Jan 29 at 12:57
24
$\begingroup$

Here is one way:

Pattern[#, Blank[]] & /@ {a, b, c, d, e, f, g, h, i, j}
(* {a_, b_, c_, d_, e_, f_, g_, h_, i_, j_} *)

An inspection of the FullForm of a_ reveals why this works:

a_ // FullForm
(* Pattern[a, Blank[]] *)

We can abbreviate slightly if we realize that the InputForm of Blank[] is _:

Pattern[#, _] & /@ {a, b, c, d, e, f, g, h, i, j}
(* {a_, b_, c_, d_, e_, f_, g_, h_, i_, j_} *)

As an alternative approach, one might think to use pattern-matching replacement instead:

Replace[{a, b, c, d, e, f, g, h, i, j}, s_Symbol :> s_, {1}]
(*
  RuleDelayed::rhs: Pattern s_ appears on the right-hand side of rule s_Symbol:>s_.
  {a_, b_, c_, d_, e_, f_, g_, h_, i_, j_}
*)

... but Mathematica issues a warning because most of the time having a pattern on the right-hand side of a rule is a mistake. In this particular case it is not an error, so we have to use Quiet to tell Mathematica that:

Quiet[Replace[{a, b, c, d, e, f, g, h, i, j}, s_Symbol :> s_, {1}], RuleDelayed::rhs]
(* {a_, b_, c_, d_, e_, f_, g_, h_, i_, j_} *)
| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ One could also seize the opportunity to write the first one with the new OperatorApplied[Pattern][_] /@ {a, b, c, d, e, f, g, h, i, j}. $\endgroup$ – Rojo May 10 at 22:31
16
$\begingroup$

A few additional alternatives to inject patterns on the rhs:

list = {a, b, c, d, e, f, g, h, i, j};

Replace[list, a_ :> (x_ /. x -> a), 1]

{a_, b_, c_, d_, e_, f_, g_, h_, i_, j_}

Replace[list, a_ :> (Pattern[#, _] &@a), 1]

{a_, b_, c_, d_, e_, f_, g_, h_, i_, j_}

Activate @ Replace[list, a_ :> Inactive[Pattern][a, _], 1]

{a_, b_, c_, d_, e_, f_, g_, h_, i_, j_}

Replace[list, a_ :> foo[a, _], 1] /. foo -> Pattern

{a_, b_, c_, d_, e_, f_, g_, h_, i_, j_}

| improve this answer | |
$\endgroup$
9
$\begingroup$

convert it to string and then deal with it

ToExpression@StringJoin[#,"_"]&/@ToString/@{a,b,c,d,e}

a shorter way

ToExpression@StringJoin[ToString@#,"_"]&/@{a,b,c,d,e}
| improve this answer | |
$\endgroup$
5
$\begingroup$

Here is a (silly?) way

Insert[Pattern/@#,Blank[],{#,2}&/@Range@Length@#]&@{a,b}
{a_,b_}

It works with held expressions

a=1;
b=2;
Insert[Pattern/@#,Blank[],{#,2}&/@Range@Length@#]&@Hold[a,b]
Hold[a_,b_]

The following is the silliest I could make it

#/.a_-> ReplacePart[#0[[1,2,1]],1-> #]&/@{a,b,c}
{a_,b_,c_}
| improve this answer | |
$\endgroup$
5
$\begingroup$

Other options to avoid the warning message:

With[{a = #}, a_] & /@ {a, b, c, d, e, f, g, h, i, j}

Pattern[{a, b, c, d, e, f, g, h, i, j}, _] // Thread

Or to suppress it:

Cases[{a, b, c, d, e, f, g, h, i, j}, a_ :> a_] // Quiet
| improve this answer | |
$\endgroup$
4
$\begingroup$

Another alternative:

Function[x, x_, Listable][{a, b, c, d, e, f, g, h, i, j}]
(*  {a_, b_, c_, d_, e_, f_, g_, h_, i_, j_}  *)

Playful alternatives: These work "accidentally", since Times is Orderless and Blank[] happens to come after the variables.

{a, b, c, d, e, f, g, h, i, j} _ /. Times -> Pattern
Pattern @@@ ({a, b, c, d, e, f, g, h, i, j} _)
| improve this answer | |
$\endgroup$
  • $\begingroup$ Very nice! One I'll try to remember. $\endgroup$ – Mr.Wizard Dec 17 '19 at 22:14
3
$\begingroup$

Yet another way to do it (triggering a warning along the way)

{a, b, c, d, e, f, g, h, i, j} /. u_Symbol /; Context[u] == "Global`" :> u_

I had not realised you could use Context in pattern matching.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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