NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 12 - Podmínky ve Swift podruhé - Ternární výraz a mocnější switch

V minulé lekci, Vícerozměrná pole ve Swift, jsme si představili vícerozměrná pole.

V dnešním Swift tutoriálu si představíme 2 další konstrukce, které souvisejí s podmínkami. Jedná se o oddechovou lekci, kterou toto téma dokončíme.

Ternární operátor

Často se nám stává, že někde potřebujeme nastavit 2 různé hodnoty podle toho, zda platí nějaká podmínka.

Příklad - Výpis pohlaví

Představme si, že máme např. pohlaví uživatele uložené jako Bool (muž by byl true) a my bychom ho chtěli převést do textu. S dosavadními znalostmi bychom napsali asi takovýto kód:

Klikni pro editaci
  • let muz = true // nějaká proměnná udávající pohlaví
    let nazevPohlavi: String
    if muz {
        nazevPohlavi = "muž"
    } else {
        nazevPohlavi = "žena"
    }
    
    print(nazevPohlavi)
    
    • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

    Výstup programu je samozřejmě následující:

    muž

    Kód je poměrně upovídaný na to, že jen přepíná mezi dvěma hodnotami. Proto programovací jazyky často podporují tzv. ternární výraz.

    Syntaxe ternárního výrazu

    Pomocí tohoto operátoru můžeme získat hodnotu podle platnosti logického výrazu. Zapíšeme jej takto:

    výraz ? hodnota1 : hodnota2

    Podmínku vložíme většinou do závorky (), pokud je složitější, poté následuje otazník ? a dvě hodnoty, které se mají vrátit. Hodnoty jsou oddělené dvojtečkou :, první se vrátí když podmínka platí a druhá když neplatí. Jak snadné! :) Název operátoru je odvozený od toho, že má 3 části (podmínka, první hodnota a druhá hodnota), proto ternární.

    Příklad - Použití ternárního výrazu

    Pojďme si ternární operátor vyzkoušet na příkladu s pohlavím:

    Klikni pro editaci
    • let muz = true
      let nazevPohlavi = muz ? "muž" : "žena"
      print(nazevPohlavi)
      
      • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

      Místo typu Bool bychom mohli samozřejmě napsat jakoukoli jinou podmínku, např. (vek >= 18) ? "zletilý" : "nezletilý".

      Vnořování ternárních operátorů

      Ternární operátory lze teoreticky zanořovat do sebe a tím reagovat i na tři a více hodnot. Nicméně ve většině případů zanořování spíše kód znepřehlední, vznikají totiž dlouhé nebo podivně zalomené řádky a není na první pohled vidět, jaká část se kdy spustí. Ukažme si, jak by se pomocí vnořování ternárních výrazů vyřešil výpis tří pohlaví:

      Klikni pro editaci
      • let pohlavi = "nevim"
        let nazevPohlavi = pohlavi == "muz" ? "muž" : pohlavi == "zena" ? "žena" : "nezname"
        print(nazevPohlavi)
        
        • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

        Pro příklad výše by bylo lepší vytvořit vlastní metodu, což si ale ukážeme až v navazujícím kurzu objektově orientovaného programování.

        Pokročilejší switch

        S konstrukcí switch jsme se již setkali v lekci Podmínky (větvení). Dnes si ukážeme její další použití, které není tak časté, ale můžete na něj narazit. Jakmile switch vykoná první case, tak se jeho provádění ukončí. Můžeme ale použít speciální klíčové slovo fallthrough a toto chování upravit.

        V jazycích jako C dokonce switch automaticky "propadává", takže je nutné psát explicitně break do každé větve.

        Příklad - Čtvrtletí

        Předpokládejme, že chceme podle měsíce v roce zjistit, jaké je čtvrtletí. Pomocí if a else by příklad vypadal následovně:

        Klikni pro editaci
        • let mesic = 2
          if mesic >= 1 && mesic <= 3 {
              print("Je první čtvrtletí")
          } else if mesic >= 4 && mesic <= 6 {
              print("Je druhé čtvrtletí")
          } else if mesic >= 7 && mesic <= 9 {
              print("Je třetí čtvrtletí")
          } else if mesic >= 10 && mesic <= 12 {
              print("Je čtvrté čtvrtletí")
          }
          
          • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

          Jak ale použít switch pro takovýto příklad? Možná by vás napadl následující zápis:

          Klikni pro editaci
          • let mesic = 11
            switch mesic {
            case 1:
                print("Je první čtvrtletí")
            case 2:
                print("Je první čtvrtletí")
            case 3:
                print("Je první čtvrtletí")
            case 4:
                print("Je druhé čtvrtletí")
            case 5:
                print("Je druhé čtvrtletí")
            case 6:
                print("Je druhé čtvrtletí")
            case 7:
                print("Je třetí čtvrtletí")
            case 8:
                print("Je třetí čtvrtletí")
            case 9:
                print("Je třetí čtvrtletí")
            case 10:
                print("Je čtvrté čtvrtletí")
            case 11:
                print("Je čtvrté čtvrtletí")
            case 12:
                print("Je čtvrté čtvrtletí")
            default:
                break
            }
            
            • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

            Příklad funguje spolehlivě, problém však je, že jsme si tímto zápisem moc nepomohli. Podobnému repetitivnímu kódu bychom se vždy měli vyhýbat.

            Definice více hodnot a rozsahu case

            Jednotlivé case ve Swiftu mohou být definované pro více hodnot. Například case 1, 2, 3, který se provede, pokud bude mít proměnná jednu z těchto hodnot.

            Ještě lepší je potom možnost využít typ Range a použít tento zápis: case 1...3. Mohli bychom zapsat také jako case 1..<4.

            Upravme náš příklad:

            Klikni pro editaci
            • let mesic = 11
              switch mesic {
              case 1, 2, 3:
                  print("Je první čtvrtletí")
              case 4...6:
                  print("Je druhé čtvrtletí")
              case 7...9:
                  print("Je třetí čtvrtletí")
              case 10...12:
                  print("Je čtvrté čtvrtletí")
              default:
                  break
              }
              
              • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

              Ukázka výstupu aplikace:

              Je čtvrté čtvrtletí.

              Tento zápis je již mnohem přehlednější. A pro podobné případy se dost dobře hodí.

              Kdybyste něčeho podobného chtěli docílit s if, tak je nutné použít metodu contains() na instanci Range. Vypadalo by to nějak takto:

              if (1...3).contains(mesic) {
                  print("Je první čtvrtletí")
              }

              Switch a propadávání

              Propadávání ve switch pomocí klíčového slova fallthrough je poměrně kuriózní záležitost a dá práci vymyslet příklad, kde by mělo alespoň smysl. Jednoduše provedení jednoho case s fallthrough uvnitř způsobí, že program pak propadne i všemi dalšími case, aniž by kontroloval jejich podmínku. Ačkoli to v praxi asi nepoužijeme, jedná se o gramatiku Swift a můžete na ni narazit v cizích kódech.

              Ukažme si jeden takový příklad, i když by šel napsat jednodušeji bez propadávání. Pokud chcete kód vyzkoušet u sebe, tak v Xcode musíte vytvořit Command Line Tool, v Playground totiž readLine() nefunguje. Nebo si prostě do konstanty vstup uložte něco jako "1gb":

              Klikni pro editaci
              • let vstup = readLine()!.trimmingCharacters(in: .whitespacesAndNewlines).lowercased().replacingOccurrences(of: "b", with: "")
                
                let jednotka: Character = vstup.last!
                var hodnota = Double(String(vstup.dropLast()))!
                
                switch(jednotka)
                {
                case "y":
                    hodnota *= 1024
                    fallthrough
                case "z":
                    hodnota *= 1024
                    fallthrough
                case "e":
                    hodnota *= 1024
                    fallthrough
                case "p":
                    hodnota *= 1024
                    fallthrough
                case "t":
                    hodnota *= 1024
                    fallthrough
                case "g":
                    hodnota *= 1024
                    fallthrough
                case "m":
                    hodnota *= 1024
                    fallthrough
                case "k":
                    hodnota *= 1024
                default:
                    break
                }
                
                print("Soubor má \(hodnota) bajtů.")
                
                • Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.

                Výstup:

                1gb
                Soubor má 1073741824.0 bajtů.

                Program převádí velikost souboru zadanou např. v megabajtech nebo gigabajtech na bajty. Jak vidíme, jednotky následují postupně za sebou a jakmile najdeme case, který odpovídá zadané jednotce, pronásobí se zadaná hodnota i v těch následujících case. To proto, že např. 1 GB má 1024 MB a ten má také 1024 KB a ten má 1024 bajtů, násobíme 1024 tedy hned 3x. Mnohem lepší by ovšem bylo uložit si jednotky do pole a to procházet cyklem, než programovat takto repetitivně to samé násobení znovu a znovu.

                Jak už jsme si řekli, ve Swiftu nedochází k automatickému propadávání u case, takže do nich nemusíme psát break. Propadnutí ale můžeme vynutit pomocí klíčového slova fallthrough. To způsobí, že program "propadne" na všechny další case, který také vykoná, zde už je jedno, jestli je splněná podmínka. Zatím jsem se s fallthrough osobně nepotkal, můžete se hodit např., když byste chtěli vykonat default blok, případě u pokročilejších konstrukcí, kde v rámci jednoho case zachytáváte více podmínek.

                V příští lekci, Cykly ve Swift podruhé - repeat...while, break a continue, na nás čeká další syntaxe okolo cyklů, na kterou můžeme narazit v cizích zdrojových kódech.


                 

                Jak se ti líbí článek?
                Před uložením hodnocení, popiš prosím autorovi, co je špatněZnaků 0 z 50-500
                Předchozí článek
                Vícerozměrná pole ve Swift
                Všechny články v sekci
                Základní konstrukce jazyka Swift
                Přeskočit článek
                (nedoporučujeme)
                Cykly ve Swift podruhé - repeat...while, break a continue
                Článek pro vás napsal Filip Němeček
                Avatar
                Uživatelské hodnocení:
                8 hlasů
                Autor se věnuje vývoji iOS aplikací (občas macOS)
                Aktivity