Výběr z řetězců

Už umíš spojovat dohromady kratší řetězce:

spojeny_retezec = 'a' + 'b'
dlouhy_retezec = 'ó' * 100

Teď se podíváme na opačný proces: jak z dlouhého řetězce dostat kratší součásti. Začneme jednotlivými znaky.

Výběr znaku

Konkrétní znak na dané pozici se z řetězce dá vybrat operací vybrání prvku (angl. subscripting), která se píše podobně jako volání funkce, jen s hranatými závorkami. Třeba takhle se dá vybrat znak na páté pozici:

pate_pismeno = 'čokoláda'[5]

print(pate_pismeno)

Funguje to? Dostala jsi opravdu páté písmeno?

Řešení

Jak sis možná už všimla, programátoři počítají od nuly. „První“ prvek má vždy číslo nula, druhý číslo jedna a tak dál.

Stejně je to i se znaky v řetězcích. První písmeno má číslo nula, druhé jedna, ... a osmé písmeno má číslo sedm.

Proč je tomu tak? K úplnému pochopení důvodů by ses potřebovala naučit něco o ukazatelích a polích, což nebude hned, takže pro teď nám bude stačit vědět, že programátoři jsou prostě divní.

Nebo aspoň že mají rádi divná čísla – jako nulu.

   [0] [1] [2] [3] [4] [5] [6] [7]

  ╭───┬───┬───┬───┬───┬───┬───┬───╮
  │ Č │ o │ k │ o │ l │ á │ d │ a │
  ╰───┴───┴───┴───┴───┴───┴───┴───╯

A když už jsme u divných čísel, co se asi stane, když budu vybírat písmena pomocí záporných čísel?

Řešení

Sekání řetězců

Kromě jednotlivých znaků můžeme vybírat i delší části – odborně podřetězce (angl. substrings).

Zkus, co dělá tenhle program:

retezec = 'čokoláda'
kousek = retezec[5:]
print(kousek)

Řešení

Dá se použít i retezec[:5], který vybere všechno až po znak číslo 5. Ne však znak 5 samotný, což je možná trochu zarážející, ale je potřeba s tím počítat. Poslední prvek není ve výběru obsažen, podobně jako range(5) neobsahuje číslo 5.

Ačkoli je tohle chování divné, má hezké důsledky. Všimni si třeba, že retezec[:5] + retezec[5:] ti dá zpět původní retezec.

Podobnému vybírání podřetězců se říká „sekání“ řetězců (angl. string slicing).

Sekání „od“ a „do“ se dá kombinovat. Zkus si to: co asi udělají následující příkazy?

retezec = 'čokoláda'
print(retezec[:4])
print(retezec[2:6])
print(retezec[-3:])
print(retezec[:])

Řešení

Určování vhodných čísel, indexů, občas vyžaduje trochu zamyšlení.

U sekání (s :) pomáhá očíslovat si „hranice“ mezi znaky, abys v tom měla lepší přehled:

  ╭───┬───┬───┬───┬───┬───┬───┬───╮
  │ Č │ o │ k │ o │ l │ á │ d │ a │
  ├───┼───┼───┼───┼───┼───┼───┼───┤
  │   │   │   │   │   │   │   │   │
  0   1   2   3   4   5   6   7   8
 -8  -7  -6  -5  -4  -3  -2  -1

  ╰───────────────╯
  'čokoláda'[:4] == 'čoko'

          ╰───────────────╯
        'čokoláda'[2:6] == 'kolá'

                      ╰───────────╯
                      'čokoláda'[-3:] == 'áda'
{
  "data": {
    "sessionMaterial": {
      "id": "session-material:2019/brno-jaro-2019-pondeli:turtle:2",
      "title": "Výběr z řetězců",
      "html": "\n          \n    \n\n    <h1>V&#xFD;b&#x11B;r z&#xA0;&#x159;et&#x11B;zc&#x16F;</h1>\n<p>U&#x17E; um&#xED;&#x161; spojovat dohromady krat&#x161;&#xED; &#x159;et&#x11B;zce:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">spojeny_retezec</span> <span class=\"o\">=</span> <span class=\"s1\">&apos;a&apos;</span> <span class=\"o\">+</span> <span class=\"s1\">&apos;b&apos;</span>\n<span class=\"n\">dlouhy_retezec</span> <span class=\"o\">=</span> <span class=\"s1\">&apos;&#xF3;&apos;</span> <span class=\"o\">*</span> <span class=\"mi\">100</span>\n</pre></div><p>Te&#x10F; se pod&#xED;v&#xE1;me na opa&#x10D;n&#xFD; proces: jak z dlouh&#xE9;ho\n&#x159;et&#x11B;zce dostat krat&#x161;&#xED; sou&#x10D;&#xE1;sti.\nZa&#x10D;neme jednotliv&#xFD;mi znaky.</p>\n<h2>V&#xFD;b&#x11B;r znaku</h2>\n<p>Konkr&#xE9;tn&#xED; znak na dan&#xE9; pozici se z&#xA0;&#x159;et&#x11B;zce d&#xE1; vybrat operac&#xED; <em>vybr&#xE1;n&#xED; prvku</em>\n(angl. <em>subscripting</em>),\nkter&#xE1; se p&#xED;&#x161;e podobn&#x11B; jako vol&#xE1;n&#xED; funkce, jen s hranat&#xFD;mi z&#xE1;vorkami.\nT&#x159;eba takhle se d&#xE1; vybrat znak na p&#xE1;t&#xE9; pozici:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">pate_pismeno</span> <span class=\"o\">=</span> <span class=\"s1\">&apos;&#x10D;okol&#xE1;da&apos;</span><span class=\"p\">[</span><span class=\"mi\">5</span><span class=\"p\">]</span>\n\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">pate_pismeno</span><span class=\"p\">)</span>\n</pre></div><p>Funguje to? Dostala jsi opravdu p&#xE1;t&#xE9; p&#xED;smeno?</p>\n<div class=\"solution\" id=\"solution-0\">\n    <h3>&#x158;e&#x161;en&#xED;</h3>\n    <div class=\"solution-cover\">\n        <a href=\"/2019/brno-jaro-2019-pondeli/beginners/str-index-slice/index/solutions/0/\"><span class=\"link-text\">Uk&#xE1;zat &#x159;e&#x161;en&#xED;</span></a>\n    </div>\n    <div class=\"solution-body\" aria-hidden=\"true\">\n        <p>Nedostala &#x2013; dostala jsi <em>&#x161;est&#xE9;</em> p&#xED;smeno.</p>\n    </div>\n</div><p>Jak sis mo&#x17E;n&#xE1; u&#x17E; v&#x161;imla, program&#xE1;to&#x159;i po&#x10D;&#xED;taj&#xED; od nuly.\n&#x201E;Prvn&#xED;&#x201C; prvek m&#xE1; v&#x17E;dy &#x10D;&#xED;slo nula, druh&#xFD; &#x10D;&#xED;slo jedna a tak d&#xE1;l.</p>\n<p>Stejn&#x11B; je to i se znaky v&#xA0;&#x159;et&#x11B;zc&#xED;ch. Prvn&#xED; p&#xED;smeno m&#xE1; &#x10D;&#xED;slo nula,\ndruh&#xE9; jedna, ... a osm&#xE9; p&#xED;smeno m&#xE1; &#x10D;&#xED;slo sedm.</p>\n<p>Pro&#x10D; je tomu tak?\nK &#xFA;pln&#xE9;mu pochopen&#xED; d&#x16F;vod&#x16F; by ses pot&#x159;ebovala\nnau&#x10D;it n&#x11B;co o ukazatel&#xED;ch a pol&#xED;ch,\nco&#x17E; nebude hned, tak&#x17E;e pro te&#x10F; n&#xE1;m bude\nsta&#x10D;it v&#x11B;d&#x11B;t,\n&#x17E;e program&#xE1;to&#x159;i jsou prost&#x11B; divn&#xED;.</p>\n<p>Nebo aspo&#x148; &#x17E;e maj&#xED; r&#xE1;di divn&#xE1; &#x10D;&#xED;sla &#x2013; jako nulu.</p>\n<div class=\"highlight\"><pre><code>   [0] [1] [2] [3] [4] [5] [6] [7]\n\n  &#x256D;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x256E;\n  &#x2502; &#x10C; &#x2502; o &#x2502; k &#x2502; o &#x2502; l &#x2502; &#xE1; &#x2502; d &#x2502; a &#x2502;\n  &#x2570;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x256F;</code></pre></div><p>A kdy&#x17E; u&#x17E; jsme u divn&#xFD;ch &#x10D;&#xED;sel,\nco se asi stane, kdy&#x17E; budu vyb&#xED;rat p&#xED;smena pomoc&#xED; z&#xE1;porn&#xFD;ch &#x10D;&#xED;sel?</p>\n<div class=\"solution\" id=\"solution-1\">\n    <h3>&#x158;e&#x161;en&#xED;</h3>\n    <div class=\"solution-cover\">\n        <a href=\"/2019/brno-jaro-2019-pondeli/beginners/str-index-slice/index/solutions/1/\"><span class=\"link-text\">Uk&#xE1;zat &#x159;e&#x161;en&#xED;</span></a>\n    </div>\n    <div class=\"solution-body\" aria-hidden=\"true\">\n        <div class=\"highlight\"><pre><span></span><span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&apos;&#x10C;okol&#xE1;da&apos;</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">1</span><span class=\"p\">])</span>  <span class=\"c1\"># &#x2192; a</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&apos;&#x10C;okol&#xE1;da&apos;</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">2</span><span class=\"p\">])</span>  <span class=\"c1\"># &#x2192; d</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&apos;&#x10C;okol&#xE1;da&apos;</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">3</span><span class=\"p\">])</span>  <span class=\"c1\"># &#x2192; &#xE1;</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"s1\">&apos;&#x10C;okol&#xE1;da&apos;</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">4</span><span class=\"p\">])</span>  <span class=\"c1\"># &#x2192; l</span>\n</pre></div><p>Z&#xE1;porn&#xE1; &#x10D;&#xED;sla vyb&#xED;raj&#xED; p&#xED;smenka od konce.</p>\n<div class=\"highlight\"><pre><code>   [0] [1] [2] [3] [4] [5] [6] [7]\n   [-8][-7][-6][-5][-4][-3][-2][-1]\n  &#x256D;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x256E;\n  &#x2502; &#x10C; &#x2502; o &#x2502; k &#x2502; o &#x2502; l &#x2502; &#xE1; &#x2502; d &#x2502; a &#x2502;\n  &#x2570;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x2534;&#x2500;&#x2500;&#x2500;&#x256F;</code></pre></div>\n    </div>\n</div><h2>Sek&#xE1;n&#xED; &#x159;et&#x11B;zc&#x16F;</h2>\n<p>Krom&#x11B; jednotliv&#xFD;ch znak&#x16F; m&#x16F;&#x17E;eme vyb&#xED;rat i del&#x161;&#xED; &#x10D;&#xE1;sti &#x2013; odborn&#x11B;\n<em>pod&#x159;et&#x11B;zce</em> (angl. <em>substrings</em>).</p>\n<p>Zkus, co d&#x11B;l&#xE1; tenhle program:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">retezec</span> <span class=\"o\">=</span> <span class=\"s1\">&apos;&#x10D;okol&#xE1;da&apos;</span>\n<span class=\"n\">kousek</span> <span class=\"o\">=</span> <span class=\"n\">retezec</span><span class=\"p\">[</span><span class=\"mi\">5</span><span class=\"p\">:]</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">kousek</span><span class=\"p\">)</span>\n</pre></div><div class=\"solution\" id=\"solution-2\">\n    <h3>&#x158;e&#x161;en&#xED;</h3>\n    <div class=\"solution-cover\">\n        <a href=\"/2019/brno-jaro-2019-pondeli/beginners/str-index-slice/index/solutions/2/\"><span class=\"link-text\">Uk&#xE1;zat &#x159;e&#x161;en&#xED;</span></a>\n    </div>\n    <div class=\"solution-body\" aria-hidden=\"true\">\n        <p>Z&#xE1;pis <code>retezec[5:]</code> vybere <em>pod&#x159;et&#x11B;zec</em> od znaku &#x10D;&#xED;slo 5 d&#xE1;l.</p>\n    </div>\n</div><p>D&#xE1; se pou&#x17E;&#xED;t i <code>retezec[:5]</code>,\nkter&#xFD; vybere v&#x161;echno <em>a&#x17E; po</em> znak &#x10D;&#xED;slo 5.\nNe v&#x161;ak znak 5 samotn&#xFD;, co&#x17E; je mo&#x17E;n&#xE1; trochu zar&#xE1;&#x17E;ej&#xED;c&#xED;,\nale je pot&#x159;eba s t&#xED;m po&#x10D;&#xED;tat.\nPosledn&#xED; prvek nen&#xED; ve v&#xFD;b&#x11B;ru obsa&#x17E;en, podobn&#x11B; jako <code>range(5)</code> neobsahuje\n&#x10D;&#xED;slo 5.</p>\n<p>A&#x10D;koli je tohle chov&#xE1;n&#xED; divn&#xE9;, m&#xE1; hezk&#xE9; d&#x16F;sledky.\nV&#x161;imni si t&#x159;eba, &#x17E;e <code>retezec[:5] + retezec[5:]</code> ti d&#xE1; zp&#x11B;t p&#x16F;vodn&#xED; <code>retezec</code>.</p>\n<p>Podobn&#xE9;mu vyb&#xED;r&#xE1;n&#xED; pod&#x159;et&#x11B;zc&#x16F; se &#x159;&#xED;k&#xE1; &#x201E;sek&#xE1;n&#xED;&#x201C; &#x159;et&#x11B;zc&#x16F;\n(angl. <em>string slicing</em>).</p>\n<p>Sek&#xE1;n&#xED; &#x201E;od&#x201C; a &#x201E;do&#x201C; se d&#xE1; kombinovat.\nZkus si to: co asi ud&#x11B;laj&#xED; n&#xE1;sleduj&#xED;c&#xED; p&#x159;&#xED;kazy?</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">retezec</span> <span class=\"o\">=</span> <span class=\"s1\">&apos;&#x10D;okol&#xE1;da&apos;</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">retezec</span><span class=\"p\">[:</span><span class=\"mi\">4</span><span class=\"p\">])</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">retezec</span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"p\">:</span><span class=\"mi\">6</span><span class=\"p\">])</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">retezec</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">3</span><span class=\"p\">:])</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">retezec</span><span class=\"p\">[:])</span>\n</pre></div><div class=\"solution\" id=\"solution-3\">\n    <h3>&#x158;e&#x161;en&#xED;</h3>\n    <div class=\"solution-cover\">\n        <a href=\"/2019/brno-jaro-2019-pondeli/beginners/str-index-slice/index/solutions/3/\"><span class=\"link-text\">Uk&#xE1;zat &#x159;e&#x161;en&#xED;</span></a>\n    </div>\n    <div class=\"solution-body\" aria-hidden=\"true\">\n        <p>Z&#xE1;pis <code>retezec[od:do]</code> vybere <em>pod&#x159;et&#x11B;zec</em> od pozice <code>od</code> do pozice <code>do</code>.\nKdy&#x17E; jednu z hodnot vynech&#xE1;&#x161;, vyb&#xED;r&#xE1; se od za&#x10D;&#xE1;dku, resp. do konce.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"n\">retezec</span> <span class=\"o\">=</span> <span class=\"s1\">&apos;&#x10D;okol&#xE1;da&apos;</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">retezec</span><span class=\"p\">[:</span><span class=\"mi\">4</span><span class=\"p\">])</span>      <span class=\"c1\"># &#x2192; &#x10D;oko</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">retezec</span><span class=\"p\">[</span><span class=\"mi\">2</span><span class=\"p\">:</span><span class=\"mi\">6</span><span class=\"p\">])</span>     <span class=\"c1\"># &#x2192; kol&#xE1;</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">retezec</span><span class=\"p\">[</span><span class=\"o\">-</span><span class=\"mi\">3</span><span class=\"p\">:])</span>     <span class=\"c1\"># &#x2192; &#xE1;da</span>\n<span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">retezec</span><span class=\"p\">[:])</span>       <span class=\"c1\"># &#x2192; &#x10D;okol&#xE1;da</span>\n</pre></div>\n    </div>\n</div><p>Ur&#x10D;ov&#xE1;n&#xED; vhodn&#xFD;ch &#x10D;&#xED;sel, <em>index&#x16F;</em>, ob&#x10D;as vy&#x17E;aduje trochu zamy&#x161;len&#xED;.</p>\n<p>U&#xA0;sek&#xE1;n&#xED; (s&#xA0;<code>:</code>) pom&#xE1;h&#xE1; o&#x10D;&#xED;slovat si &#x201E;hranice&#x201C; mezi znaky,\nabys v&#xA0;tom m&#x11B;la lep&#x161;&#xED; p&#x159;ehled:</p>\n<p><a id=\"slicing-diagram\"></a></p>\n<div class=\"highlight\"><pre><code>  &#x256D;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x252C;&#x2500;&#x2500;&#x2500;&#x256E;\n  &#x2502; &#x10C; &#x2502; o &#x2502; k &#x2502; o &#x2502; l &#x2502; &#xE1; &#x2502; d &#x2502; a &#x2502;\n  &#x251C;&#x2500;&#x2500;&#x2500;&#x253C;&#x2500;&#x2500;&#x2500;&#x253C;&#x2500;&#x2500;&#x2500;&#x253C;&#x2500;&#x2500;&#x2500;&#x253C;&#x2500;&#x2500;&#x2500;&#x253C;&#x2500;&#x2500;&#x2500;&#x253C;&#x2500;&#x2500;&#x2500;&#x253C;&#x2500;&#x2500;&#x2500;&#x2524;\n  &#x2502;   &#x2502;   &#x2502;   &#x2502;   &#x2502;   &#x2502;   &#x2502;   &#x2502;   &#x2502;\n  0   1   2   3   4   5   6   7   8\n -8  -7  -6  -5  -4  -3  -2  -1\n\n  &#x2570;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x256F;\n  &apos;&#x10D;okol&#xE1;da&apos;[:4] == &apos;&#x10D;oko&apos;\n\n          &#x2570;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x256F;\n        &apos;&#x10D;okol&#xE1;da&apos;[2:6] == &apos;kol&#xE1;&apos;\n\n                      &#x2570;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x2500;&#x256F;\n                      &apos;&#x10D;okol&#xE1;da&apos;[-3:] == &apos;&#xE1;da&apos;</code></pre></div>\n\n\n        "
    }
  }
}