22

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?

kglr
  • 394,356
  • 18
  • 477
  • 896
Rumato
  • 727
  • 3
  • 9

7 Answers7

26

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_} *)
WReach
  • 68,832
  • 4
  • 164
  • 269
  • 1
    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}. – Rojo May 10 '20 at 22:31
17

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

kglr
  • 394,356
  • 18
  • 477
  • 896
9

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}
AsukaMinato
  • 9,758
  • 1
  • 14
  • 40
5

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_}
Jacob Akkerboom
  • 12,215
  • 45
  • 79
5

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} _)
Michael E2
  • 235,386
  • 17
  • 334
  • 747
5

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
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
4

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.

mikado
  • 16,741
  • 2
  • 20
  • 54