# I can't use PatternSequence with Cases

I have a list of integers:

s = {4, 5, 5, 6, 2, 5, 3, 2, 4, 2, 1, 1, 4, 3, 4, 3, 1, 6, 3, 4};


And if I do this, both occurrences of 4 after 3 are replaced.

s //. {x___, PatternSequence[3, 4], y___} :> {x, Null, y}


But doing the two thing below with Cases gives an empty list. What's the correct way to do it? And, what if I want to find only that Seqence[3, 4] that follows something less than 6; how should I insert /;?

Cases[s, {___, PatternSequence[3, 4], ___}]

Cases[s, PatternSequence[3, 4]]


Update: This is much closer to my actual problem.

Starting with a list of unique integer points.

p1 = With[{a = 20},
Table[Round[a {Cos[t], Sin[t]}],
{t, 0, 2 Pi, 2 Pi/1000}]] // DeleteDuplicates;


With the help of Mr.Wizard and Spawn1701D I can already find the corner points (redundant for my case), and then take Complement to original p1. Can this dropping be done directly with DeleteCases let's say? (I can see the corner points aren't defined uniquely, which doesn't matter now.)

p2 = ReplaceList[p1, {___, ps : PatternSequence[
{_, y1_}, {x2_, y2_}, {x3_, _}] /; y2 == y1 && x2 == x3,
___} :> {ps}] // Map[#[[2]] &, #] &;

GraphicsRow[Graphics[{PointSize[.015],
Point@#}] & /@ {p1, p1~Complement~p2}]


• For the first Case you have to put {s} if you look at the online manual the entry for Cases you will notice that Case look inside a list for the pattern (or inside the arguments of a function H) and inside your list there isn't the pattern you are looking for. For your last question just use PatternSequence[a_,3,4]/;a<6. Apr 17, 2013 at 8:31

Your Cases pattern does not match because the default levelspec is {1}. If you use {0} your pattern matches the entire expression:

Cases[s, {___, PatternSequence[3, 4], ___}, {0}]

{{4, 5, 5, 6, 2, 5, 3, 2, 4, 2, 1, 1, 4, 3, 4, 3, 1, 6, 3, 4}}


This is probably not what you want however. Consider instead:

ReplaceList[s, {___, x : PatternSequence[3, 4], ___} :> {x}]

{{3, 4}, {3, 4}}


ReplaceList[s, {___, n_ /; n < 6, x : PatternSequence[3, 4], ___} :> {x}]

{{3, 4}}


This particular pattern can be written more tersely without PatternSequence:

ReplaceList[s, {___, n_ /; n < 6, 3, 4, ___} :> {n, 3, 4}]

{{4, 3, 4}}


I included the preceding value in the list merely to show the match.

Responding to your updated question I cannot think of a reasonable way to do that with DeleteCases because that function, like Cases, operates on elements rather than sequences of elements, which is why I turned to ReplaceList in the first place. I can at least give you cleaner code for p2:

p2 = ReplaceList[p1,
{___, {_, y1_}, a : {x2_, y2_}, {x3_, _}, ___} /; y2 == y1 && x2 == x3 :> a
]


This does perform better than using //. to perform the operation, as there are optimizations in ReplaceList to not rescan the same expressions over and over as //. will.

It is worth mentioning that if you need the positions of the elements you ultimately wish to delete you can do this:

pos = ReplaceList[p1,
{a___, {_, y1_}, {x2_, y2_}, {x3_, _}, ___} /; y2 == y1 && x2 == x3 :> 2 + Length@{a}
]


Used perhaps like:

Delete[p1, List /@ pos]


# Version 10.1 update

Mathematica 10.1 introduced SequenceCases for this task:

s = {4, 5, 5, 6, 2, 5, 3, 2, 4, 2, 1, 1, 4, 3, 4, 3, 1, 6, 3, 4};

SequenceCases[s, {n_ /; n < 6, 3, 4}]

{{4, 3, 4}}


However I cannot recommend its use for any sequences specified with patterns because it has serious performance issues; see:

As a concise example of the problem:

SeedRandom[1]
big = RandomInteger[33, 30000];

SequenceCases[big, {n_ /; n < 6, 3, 4}]                      // AbsoluteTiming
ReplaceList[big, {___, n_ /; n < 6, 3, 4, ___} :> {n, 3, 4}] // AbsoluteTiming

{3.38066, {{4, 3, 4}, {2, 3, 4}, {1, 3, 4}}}

{0.00441126, {{4, 3, 4}, {2, 3, 4}, {1, 3, 4}}}


Therefore please use ReplaceList despite the extra keystrokes.

• What I'd like really is to elegantly drop those 4 after 3 occurrences, this is why I am asking about Cases. I've done that now with the help of your answer and conditioning after PatternSequence of @Spawn1701D, but what did I do, I extracted those occurrences now via ReaplceList and then take to Complement original list. Surely I can do this with DeleteCases? Wait just a sec, I'll update the question.
– BoLe
Apr 17, 2013 at 9:10
• @BoLe I added a small update to my question. Conceptually I understand what you desire, but practically I don't think that function exists in Mathematica. There are closer operations within the String replacement tools but your need to make mathematical comparisons likely removes any efficiency advantage that would have here. Apr 17, 2013 at 9:32
• Cleaner ReplaceList, this is true. Nice alternative to complement with positioning and deleting elements.
– BoLe
Apr 17, 2013 at 9:47
• @BoLe to give credit where due I first saw that combination of ReplaceList and Length here. Come to think of it that's a closely related question and you may care to read it. Apr 17, 2013 at 9:52
• And the alternative I'll use because Complement sorts the list before releasing it, pretty. :)
– BoLe
Apr 17, 2013 at 9:55