Wolfram Computation Meets Knowledge

32 Patterns

32Patterns
MatchQ tests whether something matches a pattern.
{a, x, b} matches the pattern {_, x, _}:
MatchQ[{a, x, b}, {_, x, _}]
 
{a, b, c} doesn’t match, because it has b in the middle, rather than x:
MatchQ[{a, b, c}, {_, x, _}]
 
Any list with two elements matches the pattern {_, _}:
MatchQ[{a, a}, {_, _}]
 
A list with three elements doesn’t match the pattern {_, _}:
MatchQ[{a, a, a}, {_, _}]
 
MatchQ lets you test one thing at a time against a pattern. Cases lets you pick out all the elements (“cases”) in a list that match a particular pattern.
Find all elements that match the pattern {_, _}:
Cases[{{a, a}, {b, a}, {a, b, c}, {b, b}, {c, a}, {b, b, b}}, {_, _}]
 
Find all elements that match {b, _} (i.e. cases of b followed by something):
Cases[{{a, a}, {b, a}, {a, b, c}, {b, b}, {c, a}, {b, b, b}}, {b, _}]
 
This is what you get if you test whether each element matches {b, _}:
MatchQ[#, {b, _}] & /@ {{a, a}, {b, a}, {a, b, c}, {b, b}, {c, a}, {b, b, b}}
 
Using Select to select what matches gives the same result as Cases:
Select[{{a, a}, {b, a}, {a, b, c}, {b, b}, {c, a}, {b, b, b}}, MatchQ[#, {b, _}] &]
 
In a pattern, a|b indicates “either a or b”.
Find all cases of either a or b, followed by something:
Cases[{{a, a}, {b, a}, {a, b, c}, {b, b}, {c, a}, {b, b, b}}, {a | b, _}]
 
Let’s look at another example, based on creating a list, then picking out elements that match particular patterns.
Create a list by getting the digits of a range of numbers:
IntegerDigits[Range[100, 500, 55]]
 
Find cases that end in 5:
Cases[IntegerDigits[Range[100, 500, 55]], {_, _, 5}]
 
Find cases with 1 or 2 in the middle:
Cases[IntegerDigits[Range[100, 500, 55]], {_, 1 | 2, _}]
 
The notation __ (“double blank”) in a pattern indicates any sequence of things.
Find cases consisting of any sequence, ending with b:
Cases[{{a, a}, {b, a}, {a, b, c}, {b, b}, {c, a}, {b, b, b}}, {__, b}]
 
Find sequences ending with a or b, or beginning with c:
Cases[{{a, a}, {b, a}, {a, b, c}, {b, b}, {c, a}, {b, b, b}}, {__, a | b} | {c, __}]
 
Patterns aren’t just about lists; they can involve anything.
Pick out cases that match the pattern f[_]:
Cases[{f[1], g[2, 3], {a, b, c}, f[x], f[x, x]}, f[_]]
 
One of the many uses of patterns is to define replacements. /. (“slash dot”) performs a replacement.
Replace b with Red in a list:
{a, b, a, a, b, b, a, b} /. b -> Red
 
Replace all occurrences of 2-element lists that begin with 1:
{{1, a}, {1, b}, {1, a, b}, {2, b, c}, {2, b}} /. {1, _} -> Red
 
You can give a list of replacements to use:
{{1, a}, {1, b}, {1, a, b}, {2, b, c}, {2, b}} /. {{1, _} -> Red, {__, b} -> Yellow}
 
The “blank” pattern _ matches absolutely anything. This means, for example, that {_,_} matches any list of two elements. But what if you want to insist that the two elements be the same? You can do that using a pattern like {x_,x_}.
{_, _} matches any list of two elements, whether the elements are the same or not:
Cases[{{a, a, a}, {a, a}, {a, b}, {a, c}, {b, a}, {b, b}, {c}, {a}, {b}}, {_, _}]
 
{x_, x_} matches only lists of two identical elements:
Cases[{{a, a, a}, {a, a}, {a, b}, {a, c}, {b, a}, {b, b}, {c}, {a}, {b}}, {x_, x_}]
 
x_ is an example of a named pattern. Named patterns are especially important in replacements, because they give one way to make use of parts of what one’s replacing.
Use the named pattern x_ in a replacement:
{{1, RGBColor[1, 0, 0]}, {1, RGBColor[0, 0, 1]}, {1, RGBColor[ 1, 0, 0], RGBColor[0, 0, 1]}, {2, RGBColor[0, 1, 0], RGBColor[ 0, 0, 1]}, {2, RGBColor[0, 0, 1]}} /. {1, x_} -> {x, x, Yellow, x, x}
 
The form ab is usually called a rule. If x_ appears on the left-hand side of a rule, then whatever the x_ matches can be referred to on the right-hand side as x.
Use x in the right-hand side of the rule to refer to what x_ matches:
{f[1], g[2], f[2], f[6], g[3]} /. f[x_] -> x + 10
 
Pick out elements in the list that match f[x_], and give the result of replacing them by x+10:
Cases[{f[1], g[2], f[2], f[6], g[3]}, f[x_] -> x + 10]
 
Later on, we’ll see how named patterns are crucial to defining your own functions in the Wolfram Language.
_ pattern standing for anything (“blank”)
__ pattern standing for any sequence (“double blank”)
x_ pattern named x
a|b pattern matching a or b
MatchQ[expr,pattern] test whether expr matches a pattern
Cases[list,pattern] find cases of a pattern in a list
lhsrhs rule for transforming lhs into rhs
expr/.lhsrhs replace lhs by rhs in expr
32.1Find lists of length 3 or more beginning with 1 and ending with 9 in IntegerDigits[Range[1000]]»
Expected output:
Out[]=
32.2Find lists of three identical elements in IntegerDigits[Range[1000]]»
Expected output:
Out[]=
32.3In the digit lists for the first 1000 squares, find those that begin with 9 and end with 0 or 1. »
Expected output:
Out[]=
32.4In IntegerDigits[Range[100]] replace all 0’s by Gray and all 9’s by Orange»
Expected output:
Out[]=
32.5Make a list of the digits of 2^1000, replacing all zeros by Red»
Expected output:
Out[]=
32.6Remove the vowels a, e, i, o and u from the list of characters in “The Wolfram Language”. »
Expected output:
Out[]=
32.7Find a simpler form for Select[IntegerDigits[2^1000], #0||#1&]»
Expected output:
Out[]=
Expected output:
Out[]=
Do the names of pattern variables (x_, etc.) matter?
No. They just have to be consistent inside a given pattern. Different patterns can reuse the same name for different purposes, and the name can also appear outside the pattern.
What else can be used to define patterns?
What’s the difference between | and ||?
p |q is a pattern construct, that matches either p or q. p ||q is a logic construct, that tests whether p or q is True.
How does one say a|b?
Either “a or b” or “a vertical bar b”.
How is /. interpreted?
It’s the function ReplaceAll. Replace tries to replace a whole expression. ReplaceList gives a list of results from all possible ways to match a particular pattern.
If /. has several replacements, which one will it use?
It uses the first one that applies. If replacements apply to multiple levels of an expression, /. will use it on the outermost level.
  • Patterns for strings are discussed in Section 42.
  • Pattern matching in the Wolfram Language takes account of facts such as the equivalence of x+y and y+x, or x +(y +z) and (x +y)+z. See Section 41.
  • In writing lhsrhs, the lhs stands for “left-hand side” and the rhs for “right-hand side”.
  • Patterns are scoping constructs, in the sense that they localize names like the x in x_ to just the scope of the pattern.
  • In the rare case that /. is followed by a digit (like 0), you need to leave a space before the digit to avoid confusion with division.
Next Section