Max
Max

Reputation: 20004

List element pattern matching in Mathematica

The following pattern matches only the first element

{a, b, c, d, e} /. {start : ___, x_, stop : ___} :> {start, 1, stop}

How do I make it match all of the list elements?

UPDATE:

The slightly more extended version of my goal is to have a set of three transformation rules for different elements of the list. One rule should apply to the first element, one for the last element, and another rule for every element in the middle. Here's an example:

{a, b, c, d, e} /. {most : Repeated[_], x_} -> 
   {most, "Last"} /. {x_, rest : Repeated[_]} -> {"First", rest}

These are the rules for the first and the last element. Now I need the rule for all the elements in the middle. Hence my original question.

I've probably chosen a wrong approach, because I cannot find a straightforward way to do this. Is it possible to do this with rules?

Upvotes: 2

Views: 1746

Answers (2)

Dr. belisarius
Dr. belisarius

Reputation: 61016

You may do:

list = Range[10]
list /. {first_, middle__, last_} -> {f[first], g[middle], h[last]}  

Out

{f[1], g[2, 3, 4, 5, 6, 7, 8, 9], h[10]}  

Or if you define:

g[x_, y__] = {g[x], g[y]} /. List -> Sequence 

Then the result is

{f[1], g[2], g[3], g[4], g[5], g[6], g[7], g[8], g[9], h[10]}

Upvotes: 2

Leonid Shifrin
Leonid Shifrin

Reputation: 22579

Your question is a bit unclear. Just guessing what you meant - this will force the longest match:

In[2]:= {a, b, c, d,  e} /. {start : Longest[___], x_, stop : ___} :> {start, 1, stop}

Out[2]= {a, b, c, d, 1}

While this will give all possible outcomes of rule application, not just the first that matches:

In[3]:= ReplaceList[{a, b, c, d, e}, {start : ___, x_, stop : ___} :> {start, 1, stop}]

Out[3]= {{1, b, c, d, e}, {a, 1, c, d, e}, {a, b, 1, d, e}, {a, b, c, 1, e}, {a, b, c, d, 1}}

HTH

Edit:

Responding to a more refined version of the question, a generic answer would be

{a, b, c, d, e} /. {start_, x__, end_} :> {f[start], g[x], h[end]},

Where, by specifying the functions f,g,h one can do any kind of transformations separately on the first, last, and middle elements. Sometimes you can use rules inside rules to make it more concise, for instance:

In[7]:= {a, b, c, d, e} /. {start_, x__, end_} :> {start /. _ -> "First", 
                   Sequence @@ Replace[{x}, _ -> 1, 1], end /. _ -> "Last"}

Out[7]= {"First", 1, 1, 1, "Last"}

But the main point is that once you have destructured the list, it does not matter what you use to transform the different parts - rules again, or functions, etc - you are not confined to only use rules at that point.

Upvotes: 4

Related Questions