Dzisiaj mam jedynie mały trick na który natrafiłem a który uważam za sprytne rozwiązania problemu. Nawet nie wiedziałem, że coś takiego jest możliwe w elixir. Nie przyszło mi do głowy, żeby spróbować coś podobnego zrobić a… da się.

Problem/rozwiązanie: jak zrobić substring w Elixir?

W elixir nie ma czegoś takiego jak substring jaki znamy chociażby z JavaScript czy też C#. Więc niby taka prosta rzecz może wydawać się skomplikowana choć taka nie jest. Ale by zrozumieć, jak to działa, musimy poznać operator zakresu.

W elixir mamy coś takiego jak operator zakresu (range) którym są dwie kropki: .., możemy to wykorzystać w różny sposób, na przykład:

range = 10..100
start..end = range

Gdzie start to 10 a end to 100. Operator zakresu deklaruje więc nam listę liczb. Dodatkowo jak widać na powyższym przypadku jest możliwość wykonania na nim pattern matching i pobrania stanu początkowego i końcowego. Taki zakres możemy przekonwertować do listy dzięki metodzie Enum.to_list/1 która zwróci nam listę liczb zaczynając od 10 i idącą aż do 100 ze skokiem co jeden: 10, 11, 12 .. 100.

Dodatni zakres jest dość zrozumiały – tworzymy kolejne liczby i tyle. Ale już stworzenie zakresu ujemnego 0..-4 nie przyszło mi nigdy do głowy a przecież to nic innego jak zakres liczb od 0 do -4 -> 0, -1, -2, -3 i -4. nie wiem czemu zakładałem, że to jest po prostu niemożliwe. Byłem w błędzie :)

Wracając do naszego substring, elixir posiada metody String.slice/2 oraz String.slice/3 które umożliwiają nam to samo co substring. Metoda String.slice/3 jest standardową metodą przyjmując ciąg znaków, początek i długość – nic nadzwyczajnego, więc to pominę.

Zaś metoda String.slice/2 przyjmuje jako drugi parametr zakres, który może wyglądać tak:

String.slice "gutek", 1..-1

Co to zrobi? Zwróci nam to utek a dokładnie mówiąc zwróci nam wynik działania wzięcia substring od indeksu 1 do końca słowa.

String.slice "gutek", 1..-2

Już zwróci nam ute – i g i k zostaną ucięte. Jeżeli nie interesuje nas ucinanie końcówki to możemy wykonać polecenie bez minusów:

String.slice "gutek", 1..2

Które zwróci ut.

Tak jaka przy dodatnich zakresach sprawa jest dość jasna: weź znak z miejsca START i weź tylko END znaków. Tak przy minusie to zaczyna być trochę bardziej skomplikowane na tyle że sam nie mogę jakoś tego rozsądnie dobrać w słowa. Ale można powiedzieć, weź znak z miejsca START i następne aż do END znaku od końca. Czyli przy -1 to będzie do k, przy -2 to e, przy -3 do t itd.

Jeżeli zaś jako START podamy ujemny indeks, to tak jakbyśmy zaczynali od znaku START od końca (czyli jak podamy -2 to będzie to e) i następnie znów możemy podać albo ujemną liczbę albo dodatnią jako END. Przy dodatniej, to tak jakbyśmy liczyli od lewej strony:

String.slice "gutek", -2..1
""

String.slice "gutek", -2..3
"e"

String.slice "gutek", -2..4
"ek"

Przy ujemnym END po prostu liczymy od prawej strony:

String.slice "gutek", -2..-3
""

String.slice "gutek", -2..-2
"e"

String.slice "gutek", -2..-1
"ek"

Zrozumiałe? Mi trochę zrozumienie tych wartości minusowych zajęło ;(

Ale zarazem fajna i ciekawa opcja robienia substring.

PS.: slice dlatego, że w końcu ciągi znaków to lista znaków… ;)