Do you want to pick up from where you left of?
Take me there

Reťazce

Reťazce, Charlisty, Grafémy a Codepointy

Reťazce

Reťazce v Elixire nie sú nič iné, než sekvencie bajtov. Pozrime sa na príklad:

iex> string = <<104,101,108,108,111>>
"hello"
iex> string <> <<0>>
<<104, 101, 108, 108, 111, 0>>

Spojením reťazca s bajtom 0 IEx zobrazí reťazec ako binárny zoznam, pretože už viac nie je platný reťazec. Tento trik nám môže pomôcť pri prezeraní bajtov akéhokoľvek reťazca.

POZNÁMKA: Použitím syntaxe << >> hovoríme kompilátoru, že elementy vo vnútri sú bajty.

Charlisty

Doslova: zoznamy znakov. Reťazce sú v Elixire interne reprezentované sekvenciami bajtov, nie poľami znakov ako v iných jazykoch. Elixir má však aj aj typ char list (zoznam znakov). Kým reťazce sú uzavreté v dvojitých úvodzovkách, charlisty sú uzavreté v jednoduchých úvodzovkách.

Aký je medzi nimi rozdiel? Každá hodnota v charliste je Unicode hodnotou daného znaku, zatiaľ čo reťazec je kódovaný pomocou UTF-8. Napríklad:

iex(5)> 'hełło'
[104, 101, 322, 322, 111]
iex(6)> "hełło" <> <<0>>
<<104, 101, 197, 130, 197, 130, 111, 0>>

Pri programovaní v Elixire zvyčajne používame reťazce, nie charlisty. Podpora charlistov je v Elixire hlavne kvôli niektorým Erlangovým modulom, ktoré ju vyžadujú.

Viac informácii nájdete v oficiálnej príručke.

Grafémy a Codepointy

Codepointy sú unicode znaky reprezentované jedným alebo viacerými bajtami, v závislosti od UTF-8 kódovania. Znaky mimo rozsahu US ASCII sú vždy reprezentované minimálne dvoma bajtmi. Napríklad znaky abecedy s diakritikou (á, ñ, è, …) bývajú kódované dvoma bajtami, znaky ázijských jazykov (napr. čínske znaky) dokonca troma až štyrmi bajtmi. Graféma pozostáva z viacerých codepointov, ktoré sú však vo výsledku vykreslené ako jediný znak.

Modul String poskytuje dve metódy, ktorými ich vieme získať: graphemes/1 a codepoints/1. Ukážme si použitie:

iex> string = "\u0061\u0301"
"á"

iex> String.codepoints string
["a", "́"]

iex> String.graphemes string
["á"]

Funkcie pre prácu s reťazcami

Ukážme si niektoré z najdôležitejších fukcií z modulu String. Ich kompletný zoznam aj s príkladmi použitia nájdete v oficiálnej dokumentácii modulu String.

length/1

Vráti počet grafém v reťazci.

iex> String.length "Čučoriedka"
10

replace/3

Vráti nový reťazec, ktorý vznike nahradením sekvencie (vzoru) v pôvodnom reťazci inou sekvenciou.

iex> String.replace("Hello", "e", "a")
"Hallo"

duplicate/2

Vráti nový reťazec, ktorý vznikne n-násobným zopakovaním pôvodného reťazca.

iex> String.duplicate("Oh my ", 3)
"Oh my Oh my Oh my "

split/2

Vráti zoznam reťazcov, ktorý vznikne rozdelením pôvodného reťazca podľa danej sekvencie.

iex> String.split("Hello World", " ")
["Hello", "World"]

Cvičenia

Prejdime si jednoduché cvičenia, aby sme ukázali, že sú nám reťazce jasné!

Anagramy

Reťazce A a B považujeme za anagramy, ak existuje spôsob, ako poprehadzovaním znakov v A dostaneme B (a naopak). Napríklad:

Takže, ako v Elixire zistíme, či sú dva reťazce anagramami? Najjednoduchším riešením je jednoducho abecedne zoradiť grafémy každého reťazca a následne oba utriedené zoznamy porovnať. Vyskúšajme to:

defmodule Anagram do
  def anagrams?(a, b) when is_binary(a) and is_binary(b) do
    sort_string(a) == sort_string(b)
  end

  def sort_string(string) do
    string
    |> String.downcase()
    |> String.graphemes()
    |> Enum.sort()
  end
end

Najprv sa pozrime na funkciu anagrams?/2. Hneď v hlavičke kontrolujeme, či sú prijaté hodnoty argumentov binary (sekvencie bajtov) - takto v Elixire zisťujeme, či je hodnota reťazec.

V tele funkcie voláme pre každý z argumentov funkciu sort_string?/1, ktorá reťazec konvertuje na malé písmená (lowercase), potom z neho spraví zoznam grafém pomocou String.graphemes/1 a ten utriedi podľa abecedy pomocou Enum.sort/1. Oba takto získané zoznamy nakoniec porovnáme. Jednoduché, však?

Pozrime sa na výstup v iex:

iex> Anagram.anagrams?("Hello", "ohell")
true

iex> Anagram.anagrams?("María", "íMara")
true

iex> Anagram.anagrams?(3, 5)
** (FunctionClauseError) no function clause matching in Anagram.anagrams?/2

    The following arguments were given to Anagram.anagrams?/2:

        # 1
        3

        # 2
        5

    iex:11: Anagram.anagrams?/2

Ako môžeme vidieť, posledné volanie funkcie anagrams? vrátilo FunctionClauseError. Tento nám hovorí, že v našom module neexistuje funkcia, ktorá by príjmala dva ne-binárne (ne-reťazcové) argumenty. A to je správne, pretože sme chceli pracovať len s dvoma reťazcami, ničím iným.

Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!