Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern match on substring in Elixir

Tags:

elixir

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
like image 277
snewcomer Avatar asked Jan 12 '18 17:01

snewcomer


People also ask

What is pattern matching in Elixir?

Pattern matching allows developers to easily destructure data types such as tuples and lists. As we will see in the following chapters, it is one of the foundations of recursion in Elixir and applies to other types as well, like maps and binaries.

How do I match a pattern in SQL?

SQL pattern matching enables you to use _ to match any single character and % to match an arbitrary number of characters (including zero characters). In MySQL, SQL patterns are case-insensitive by default. Some examples are shown here. Do not use = or <> when you use SQL patterns.

What is pattern matching command?

Pattern matching is used by the shell commands such as the ls command, whereas regular expressions are used to search for strings of text in a file by using commands, such as the grep command.


2 Answers

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
like image 187
Dogbert Avatar answered Dec 04 '22 12:12

Dogbert


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:

One example using Regex:

@matched_string "x-wat"

def match?(string) do
  ~r/^(.+; )?(#{@matched_string})(; [^\s]+)?$/ |> Regex.match?(string)
end

Verify:

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
like image 37
ryanwinchester Avatar answered Dec 04 '22 13:12

ryanwinchester