As we know that, Ruby 2.7 has introduced pattern matching (Here are the slides to pattern matching for a quick refresher).
Now, Ruby has added support for find pattern in the pattern matching.
Before
If we wanted to pattern match with one of the items in an array, it was not possible before as demonstrated below:
json = {name: "John", friends: [{name: "Alex", age: 24}, {name: "Don", age: 25}]}
case json
in {name: "John", friends: [{name: "Alex", age: age}]}
p age
end
NoMatchingPatternError ({:name=>"John", :friends=>[{:name=>"Alex", :age=>24}, {:name=>"Don", :age=>25}]})
After
Now we can specify *
before and after the item if we want to match an element in an array which contains more than one item as shown below:
json = {name: "John", friends: [{name: "Alex", age: 24}, {name: "Don", age: 25}]}
case json
in {name: "John", friends: [*,{name: "Alex", age: age}, *]}
p age
end
# => 24
Let’s have a look at some more examples:
case ["a", "b", 23, "c", "d", "e", 48]
in [*pre, String => x, String => y, *post]
p pre # => []
p x # => "a"
p y # => "b"
p post # => [23, "c", "d", "e", 48]
end
In this example, since the pattern specifies to have two strings consecutively, an empty array is assigned to pre, "a"
is assigned to x
, "b"
is assigned to y
. This is because the consecutive strings are present in the starting of the array, which leaves no element to pre
. Finally [23, "c", "d", "e", 48]
is assigned to post
as those are the remaining elements in the array.
case ["alpha", 1, "beta", "gamma", 2, "a", "b", "c", 3]
in [*pre, String => x, String => y, *post]
p pre # => ["alpha", 1]
p x # => "beta"
p y # => "gamma"
p post # => [2, "a", "b", "c", 3]
end
In this example, the pattern being matched is the same as above, but input is changed. As you can see in the given input, the first consecutive strings are "beta"
and "gamma"
. Hence all the elements present before the pattern are assigned to pre
. "beta"
is assigned to x
and "gamma"
is expected to y
as expected. The remaining elements are assigned to post
.