Hlavní navigace

Ruby z rychlíku (2)

Dalibor Šrámek 15. 2. 2002

V dnešním pokračování naší seznamovací minisérie se podíváme na další datové typy a operátory, řídící struktury a povíme si také něco o podpoře regulárních výrazů.

Proměnné a operátory (pokračování)

Pole

K uložení jednorozměrného pole slouží objekt třídky Array. Prvkem pole může být libovolný další objekt včetně pole samotného, čímž lze docílit vícerozměrných polí. Array poskytuje automatickou alokaci paměti a kontrolu mezí indexů. Podobně jako u řetězců i pro pole existuje značné množství metod. Nejlépe si vše osvětlíme na příkladech:

def puts_ary ary      # uděláme si funkci na výpis pole
  puts ary.join ', '  # vypiš prvky spojené čárkami a mezerami do řetězce
end

a=['p','o','l','e']   # inicializujeme pole čtyř jednoznakových řetězců

puts a.length         # počet prvků pole (také můžeme použít a.size)
puts a[1]             # prvek s indexem 1 (indexy začínají od nuly)
puts a[-1]            # první prvek od konce pole
puts a.index 'o'      # index prvku, který se rovná 'o'

puts_ary a[2..3]      # pole tvořené prvky s rozsahem indexů 2..3

a[4]=1                # přiřadíme další prvek, pole se automaticky rozšíří
puts_ary a
a.delete_at 4         # zase prvek smažeme (prvek s indexem 4)
puts_ary a

puts_ary a.sort       # získáme seřazené prvky pole
puts_ary a.reverse    # prvky pole v obráceném pořadí

a.push 'x'            # přidání prvku na konec pole
puts_ary a
puts a.pop            # odebrání prvku z konce pole
puts_ary a
a.unshift 'x'         # přidání prvku na začátek pole
puts_ary a
puts a.shift          # odebrání prvku ze začátku pole
puts_ary a

Zobrazí se:

4
o
e
1
l, e
p, o, l, e, 1
p, o, l, e
e, l, o, p
e, l, o, p
p, o, l, e, x
x
p, o, l, e
x, p, o, l, e
x
p, o, l, e

Pomocí metod push, pop, shift a unshift lze realizovat klasické struktury zásobníku a fronty. Tyto metody mění dané pole. U jiných platí stejné pravidlo s vykřičníkem jako u řetězců (pro metodu sort existuje ekvivalent sort! atd.)

Hash

Hash je struktura podobná poli (někdy se mu také říká asociativní pole), ale narozdíl od pole, kde je jako index pevně stanoven integer, může být indexem hashe prakticky libovolný objekt. K ilustraci opět použijeme jednoduchý příklad:

a={'jedna'=>'I',     # hash můžeme inicializovat přiřazení
   'dve'=>'II',      # klíč=>hodnota oddělených čárkami
   'tri'=>'III',
   'ctyri'=>'IV',    # v tomto případě použijeme pro klíč i hodnoty
   'pet'=>'V'        # řetězcové konstanty
}

puts a['dve']        # hodnota s klíčem 'dvě'
puts a['deset']      # hodnota s klíčem 'deset' (není tam, vrací se nil)
a['deset']='X'       # přiřadíme klíči 'deset' hodnotu 'X'
puts a['deset']      # hodnota s klíčem 'deset'
puts a.index 'V'     # klíč hodnoty 'V'
puts a.invert['IV']  # metoda invert vytvoří obrácený hash (hodnota=>klíč)
puts a.length        # počet záznamů v hashi

Po spuštění získáme:

II
nil
X
pet
ctyri
6

Je možné ukládat do hashů pole a naopak, což nabízí značnou flexibilitu pro konstrukci různých datových struktur. Další možnosti práce s poli a hashi uvidíme v sekci o iterátorech.

Operátory

Samozřejmostí jsou operátory pro běžné aritmetické operace a obvyklé relační operátory. Podívejme se na několik dalších, které by nás mohly zajímat:

  • vícenásobné přiřazení umožňuje zápis proměnná1,pro­měnná2=hodnota1,hod­nota2
  • operátor umocňování – 2**3 znamená dvě na třetí
  • operátor porovnání a< ⇒ vrací –1, když je a menší než b, 0, když je a rovno b a 1, když je a větší než b
  • ternární operátor jistě znají programároři v C – ve tvaru podmínka?hodno­ta1:hodnota2 nabývá hodnoty1, pokud je podmínka vyhodnocena jako true, jinak nabývá hodnoty2
  • metoda between? – použitím prakticky operátor, vrací true, pokud se číslo nachází mezi dvěma zadanými parametry
  • operátor + umožňuje spojovat za sebe dva řetězce
  • operátor * umožňuje řetězec několikrát zopakovat

O použití se snadno přesvědčíme na příkladu:

a,b,c=1,2,3           # do a,b a c postupně přiřadíme 1,2 a 3
puts "#{a+b+c}"       # součet a,b a c
puts 2**5             # dvě na pátou
puts 3<=>5            # porovnání 3 a 5
puts 3>4?1:2          # pokud platí 3>4, zobraz 1, jinak 2
puts 4.between?(3,5)  # je 4 mezi 3 a 5?
puts 'a'+'b'          # spojení řetězců
puts 'a'*3            # opakování řetězce

Získáme:

6
32
-1
2
true
ab
aaa

Regulární výrazy

Regulární výrazy jsou mocnou zbraní skriptovacích jazyků a do Ruby jsou elegantně integrovány. Pro naše účely postačí velmi zjednodušená a stručná pravidla:

  • regulární výraz se zapisuje mezi dvě lomítka
  • operátor =~ vrací pozici, na které v řetězci na levé straně začíná podřetězec, který vyhovuje regulárnímu výrazu na pravé straně (pokud takový podřetězec není nalezen, vrací nil)
  • negovanou variantou operátoru =~ je !~ (návratovými hodnotami jsou v tomto případě pouze true a false)

Více osvětlí několik jednoduchých příkladů:

puts 'ahoj'=~/ho/
puts 'ahoj'=~/kk/
puts 'ahoj'!~/ho/
puts 'ahoj'!~/kk/

# složitější regulární výraz pro jednoduchou kontrolu, zda
# má řetězec formát datumu d.m.rrrr
puts '2.2.2002'=~/^[0-9][0-9]?\.[0-9][0-9]?\.[0-9]{4}$/
puts '245.2.2002'=~/^[0-9][0-9]?\.[0-9][0-9]?\.[0-9]{4}$/

Po spuštění uvidíme:

1
nil
false
true
0
nil

Regulární výrazy se používají i jako parametry pro některé metody. Na ukázku si doplníme znalosti metod třídy String:

s='Perl Pike Python Perl Pike Python Perl Pike Python'
puts s
s.sub!(/Perl/,'Ruby')     # nahraď první výskyt slova 'Perl' slovem 'Ruby'
s.gsub!(/Python/,'Ruby')  # nahraď každý výskyt slova 'Python' slovem 'Ruby'
puts s

Vypíše:

Perl Pike Python Perl Pike Python Perl Pike Python
Ruby Pike Ruby Perl Pike Ruby Perl Pike Ruby

Použití regulárních výrazů je daleko více. Navíc jsme se zabývali jen konstantními výrazy, ale regulární výraz je v Ruby objekt jako každý jiný a je možné ho bez problémů vytvářet za běhu programu.

Řídící struktury

Podmínky

Bez podmíněných příkazů a cyklů bychom se v programování daleko nedostali. Už jsem se setkali s podmínkou if. Tělo podmínky je zpracováno pouze tehdy, je-li výraz vyhodnocen jako true.

a=10
if a>15 then puts 'a>15'     # tělo podmínky je oddělené slovem 'then'
elsif a>10 then puts 'a>10'
elsif a>5                    # tělo podmínky je na novém řádku
  puts 'a>5'
else
  puts 'a<=5'
end

Výsledkem je pochopitelně:

a>5

Použití then není povinné, pokud tělo podmínky začíná až na dalším řádku. Obrácenou podmínku lze realizovat pomocí příkazu unless.

Cykly

Základním cyklem při programování je while. Tělo cyklu se provádí tak dlouho, dokud je výraz vyhodnocován jako true.

a=0
b=[]              # prázdné pole
while a<5
  b.push a        # přidáme hodnotu z a na konec pole b
  a+=1
end
puts b.join ', '  # join vrací řetězec s hodnotami pole spojenými parametrem

Program vypíše:

0, 1, 2, 3, 4

Jak příkaz if, tak while lze využít ještě jedním elegantním způsobem:

a=0
b=[]
puts 'O.K.' if a==0
b.push a+=1 while a<5
puts b.join ', '

Výsledkem je:

O.K.
1, 2, 3, 4, 5

Zatímco podmínka if se chová podle očekávání, cyklus poskytuje jiné výsledky než v předchozím případě. Je to způsobeno tím, že již před uložením do pole je proměnná a inkrementována.

Iterátory

Než si ukážeme, co je to iterátor, řekneme si, jak lze v Ruby vytvořit blok kódu. Blok není nic jiného než určitým způsobem ohraničený kousek kódu. Ohraničení lze provést buď složenými závorkami, nebo klíčovými slovy do a end. Sám o sobě nemá blok velký smysl, lze ho však předat jako parametr metodě, která ho může opakovaně volat. Taková metoda se nazývá iterátor.

3.times { print '*' }         # s metodou 'times' jsme se již setkali -
puts                          # provede blok tolikrát, kolik je hodnota čísla,
3.times { |n| print n }       # a hodnotu iterace může do bloku předávat jako
puts                          # parametr
3.upto(5) { |n| print n }     # spolu s metodami 'upto' a 'step' prakticky
puts                          # nahrazuje for cyklus, který v ruby není
3.step(10,2) { |n| print n }
puts

a=['a','b','c']               # malé pole znaků

a.each { print '*' }          # pole má také iterátory - each iteruje přes
puts                                 # všechny prvky
a.each { |n| puts "#{n}, Hello!"  }  # do bloku předává aktuální prvek

b=a.select { |x| x>='b'}  # v tomto případě vrací metoda 'select' jen prvky,
puts b.join ', '          # pro které volaný blok vrací true

Výsledkem bude:

***
012
345
3579
***
a, Hello!
b, Hello!
c, Hello!
b, c

Iterátorů je v Ruby mnohem více a snadno si lze také vytvořit vlastní. Největší využití najdou zřejmě při nahrazování běžných cyklů, a zejména pro práci s prvky kontejnerů – tj. s poli, hashi a dalšími.


Příště se podíváme na to, jak se v Ruby pracuje se soubory a sokety, na ošetřování výjimek, standardní knihovnu a chybět nebude ani jeden větší demonstrační příklad.

Našli jste v článku chybu?

19. 3. 2007 0:26

Mahony (neregistrovaný)
Nic si z toho nedelej clovece:) Skolu o ktere mluvis jsem vystudoval taky a ver, ze uroven vyucovani zakladu programovani je tam jeste pomerne dobra. Bohuzel nesmis narazit na nejmenovaneho profesora D. :))

Na vysoke (FAV - ZCU Plzen) se zaklady programovani ucili na Jave. Rovnou se jelo na objektovy model programovani, bez ohledu na to jestli uz to clovek nekdy videl nebo ne. Priznavam, ze nemit znalosti programovani uz ze zakladky a to, ze me to bavi a ucim se sam, tak nevim jak bych tam poc…

21. 2. 2002 22:13

Alesak (neregistrovaný)

Ahoj, mam par dotazu:
-jak se to vykonava, preklada se to zase do bytecodu? Jak je to rychly?
-a jestli to ma bytecod, umoznuje to to co smalltalk, tzn vsechno plne dynamicky?
-ma to mapovani do CORBy?
dik, Ales
p.s. nemuzu si pomoct, pripomina mi to Objective C






Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

120na80.cz: Bojíte se encefalitidy?

Bojíte se encefalitidy?

Lupa.cz: Slevové šílenství je tu. Kde nakoupit na Black Friday?

Slevové šílenství je tu. Kde nakoupit na Black Friday?

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

Podnikatel.cz: Vládu obejde, kvůli EET rovnou do sněmovny

Vládu obejde, kvůli EET rovnou do sněmovny

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

Lupa.cz: Není sleva jako sleva. Jak obchodům nenaletět?

Není sleva jako sleva. Jak obchodům nenaletět?

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

Lupa.cz: UX přestává pro firmy být magie

UX přestává pro firmy být magie

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

DigiZone.cz: NG natáčí v Praze seriál o Einsteinovi

NG natáčí v Praze seriál o Einsteinovi

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...