I’m curious if there is a better way to remove the first and last character of a given string using pattern matching.
Basically, if an initial string is -
"hello", my function should output -
My very quick implementation is:
def remove_letters(<<_::binary-size(1)>> <> tail) do
length = byte_size(tail)
<<result::binary-size(length - 1), ext::binary>> = tail
It works, but I’m curious if there is a way I can use a smarter pattern-matching approach in the function head to avoid extra steps in the function body?!
Thank you so much in advance!
I think your code would return
ell since it removes both first and last bytes? One small note - your code only works on single-byte characters (not UTF-8).
On more recent OTP versions you can also do:
def remove_first_and_last(string) do
<<_first::binary-1,mid::binary-size(byte_size(string) - 2),_last::binary-1>> = string
yeah, you may need to consider something like
[head, tail] = Regex.run(~r/^.(.+).$/, “hello”)
would return “hello” in head and “ell” in tail
Yeah, I’m pretty aware of those approaches.
I was specifically curious about string pattern matching!
Thank you though! I appreciate it!
Yes!!! Exactly what I was curious about!
I knew it was possible!
Adding it to my knowledge library
Thank you so much! Really really appreciate it!
Maybe a stupid question, but can it be done in the function head? Probably not, as you would have stated it that way, if it was possible.
You need to first get the size of the string, which cannot be done with pattern matching alone.
This is firmly in “can but should not be done” territory, because
String.reverse is expensive:
def remove_letters(<<_::binary-size(1)>> <> tail), do: do_remove_letters(String.reverse(tail))
defp do_remove_letters(<<_::binary-size(1)>> <> liat), do: String.reverse(liat)
If you know the start of the string (super rare) you could match using this:
iex(1)> fun = fn
...(1)> "h" <> rest -> rest
...(1)> other -> other
#Function<42.3316493/1 in :erl_eval.expr/6>
iex(3)> fun.("won't match")