Reputation: 2135
How can I pattern match on a string where passing either side of the semicolon will return true? In other words, is there a simple way to pattern match it contains the substring?
@matched_string "x-wat"
def match(@matched_string), do: true
match("x-wat") # true
match("x-wat; s-wat") # true
match("s-wat; x-wat") # true
match("s-wat") # false
match("x-wat-y") #false
Upvotes: 7
Views: 6455
Reputation: 12157
You can't for the reasons @Dogbert explained, but there are lots of ways to check for substrings.
If you didn't have constraints, you could just do
iex> "s-wat; x-wat" =~ "x-wat"
true
iex> String.contains? "s-wat; x-wat", "x-wat"
true
But you have some constraints so you can get creative. I'll add another example on top of existing answers:
Regex
:@matched_string "x-wat"
def match?(string) do
~r/^(.+; )?(#{@matched_string})(; [^\s]+)?$/ |> Regex.match?(string)
end
iex(1)> import Regex
Regex
iex(2)> matched_string = "x-wat"
"x-wat"
iex(3)> r = ~r/^(.+; )?(#{matched_string})(; [^\s]+)?$/
~r/^(.+; )?(x-wat)(; [^\s]+)?$/
iex(4)> match?(r, "x-wat")
true
iex(5)> match?(r, "x-wat; s-wat")
true
iex(6)> match?(r, "s-wat; x-wat")
true
iex(7)> match?(r, "s-wat")
false
iex(8)> match?(r, "x-wat-y")
false
Upvotes: 2
Reputation: 222448
No, this cannot be done with pattern matching. You can match the prefix of a string or if you know the length of each part in the beginning of the string, you can specify the size of those and match that e.g. <<_::size(4), @matched_string, _::binary>>
, but you can't in general match any arbitrary substring. In this case, you can instead split on ;
, trim the strings, and check if it contains "x-wat"
:
def match(string) do
string |> String.split(";") |> Enum.map(&String.trim/1) |> Enum.member?(string)
end
Upvotes: 14