03. Числови типове. Масиви. Речници

03. Числови типове. Масиви. Речници

03. Числови типове. Масиви. Речници

13 октомври 2014

Какво предстои

днес и в следващите няколко лекции

Темпо

С-бира-не

сряда

Инсталиране на Ruby

последен срок за промоцията

Pull Requests

revisited

Първа задача

предварителни впечатления

Правила на Кент Бек за прост и ясен дизайн

припомняме от миналия път

My guiding light is Kent Beck's rules of Simple Design (източник):

  1. The code must first be correct (as defined by tests);
  2. then it should be a clear statement of the design (what J.B.Rainsberger calls "no bad names");
  3. then it should contain no duplication (of text, of ideas, or of responsibility);
  4. and finally it must be the smallest code that meets all of the above.

It's time to stop refactoring when the code makes a reasonable stab at meeting those goals, and when any further changes would add no further benefit.

Второ предизвикателство

Типове данни

Досега говорихме за:

Числа

Числова йерархия

Рационални числа

Комплексни числа

И такъв вграден тип има, Complex (документация):

Complex(1)           # (1+0i)
Complex(2, 3)        # (2+3i)
Complex('0.3-0.5i')  # (0.3-0.5i)
Complex('2/3+3/4i')  # ((2/3)+(3/4)*i)

3.to_c               # (3+0i)
0.3.to_c             # (0.3+0i)
'0.3-0.5i'.to_c      # (0.3-0.5i)
'2/3+3/4i'.to_c      # ((2/3)+(3/4)*i)
'1@2'.to_c           # (-0.4161468365471424+0.9092974268256817i)

Кратко проучване

Колко от вас са запознати със следните неща:

Минимално необходимо знание за всеки програмист. Поставете си го за цел.

Отклониение

#to_s и #inspect

Един обект се обръща до низ с #to_s. Има и друг вариант, #inspect, който го обръща до текстов низ, изглеждащ като ruby код. Целта е инспектиране.

Преди това

хилядите значения на диез

Масиви

Масиви

индексиране

numbers = [:zero, :one, :two]
numbers[1]   # :one
numbers[10]  # nil
numbers[-1]  # :two

numbers[5] = :five
numbers[5]   # :five
numbers      # [:zero, :one, :two, nil, nil, :five]

Масиви

fetch

Array#fetch хвърля грешка или връща друга стойност, при индексиране извън обема на масива:

numbers = [:zero, :one, :two]

numbers.fetch(1)            # :one

numbers.fetch(10)           # error: IndexError
numbers.fetch(10) { |n| puts "#{n} isn't in array" } # вместо IndexError, се изпълнява кодът между { }

numbers.fetch(10, :dunno)   # :dunno
numbers[10] or :dunno       # като предното, ама не точно

Ползва се по-рядко, отколкото си мислите.

Масиви

типичните методи

numbers = [3, 1, 2, 4]
numbers.length  # 4
numbers.size    # 4
numbers.sort    # [1, 2, 3, 4]
numbers.reverse # [4, 2, 1, 3]
numbers[1..2]   # [1, 2]

sort и reverse връщат нов масив, без да променят numbers.

Масиви

#include?

#include? ви казва дали масив съдържа даден елемент.

prime_digits = [2, 3, 5, 7]

prime_digits.include? 2    # true
prime_digits.include? 4    # false

Внимание: линейно търсене. Подходящо за малки списъци.

Масиви

забавни оператори

[:a, :b, :c] + [:d, :e]             # [:a, :b, :c, :d, :e]
[:a, :b, :c, :b, :a] - [:b, :c, :d] # [:a, :a]
[:a, :b, :c] & [:b, :c, :d]         # [:b, :c]
[:a, :b, :c] | [:b, :c, :d]         # [:a, :b, :c, :d]

& и | конкатенират списъците и премахват повторенията.

В Ruby има множества, които са по-удачни в повечето случаи.

Масиви

мутиране

numbers = [1, 2, 3]

numbers << 4
p numbers   # [1, 2, 3, 4]

numbers.insert 0, :zero
p numbers   # [:zero, 1, 2, 3, 4]

result = numbers.delete_at(0)
p result    # :zero
p numbers   # [1, 2, 3, 4]

Масиви

push и pop

stack = [1, 2, 3]

stack.push 4
p stack         # [1, 2, 3, 4]

top = stack.pop
p stack         # [1, 2, 3]
p top           # 4

#shift и #unshift са аналогични, но работят с началото на масива.

Масиви

разни други методи

[1, 2, 3].join("-")        # "1-2-3"
[1, 2, 3].permutation      # сещате се какво връща
[1, 2].product([3, 4])     # [[1, 3], [1, 4], [2, 3], [2, 4]]
[[1, 2], [3, 4]].transpose # [[1, 3], [2, 4]]
[1, 2, 3, 4].shuffle       # разбърква масива произволно

Има редица такива методи, които може да намерите в Ruby Doc.

Документация

свиквайте с нея отсега

Масиви

последната запетая

Може да оставите запетая след последния елемент на масива. Така редовете се разместват по-лесно. Важи и за хешове.

songs = [
  'My Favorite Things',
  'Alabama',
  'A Love Supreme',
]

Масиви

пърладжийски истории

Има специален синтаксис за масив от думи.

%w(chunky bacon)     == ['chunky', 'bacon']
%w[a b c]            == ['a', 'b', 'c']
%w{cool stuff}       == ['cool', 'stuff']
%w<coffee tea water> == ['coffee', 'tea', 'water']
%w|foo bar|          == ['foo', 'bar']

Може да използвате различни видове символи, които да ограждат думите от масива:

! @ # $ * - _

Този списък от символи е непълен.

Масиви

Array#slice voodoo

Масиви

Array#slice

numbers = [1, 2, 3, 4, 5, 6]

numbers[0..2]   # [1, 2, 3]
numbers[-3..-1] # [4, 5, 6]
numbers[1, 1]   # [2]

numbers[0..2] = [:wat]

numbers         # [:wat, 4, 5, 6]

Масиви

итерация

Итерира се с #each, както всичко останало в Ruby:

primes = [2, 3, 5, 7, 11]

primes.each { |n| puts n }

primes.each do |n|
  puts n
end

Sidenote: for

...или как да губим точки

"Къдрави скоби" и do/end

Хешове

Хешове

общи факти

Хешове

индексиране

numbers = {:one => :eins, :two => :zwei}

numbers[:one]     # :eins
numbers[:three]   # nil

numbers[:three] = :drei

numbers[:three]                     # :drei
numbers.fetch(:four, :keine_ahnung) # :keine_ahnung
numbers.fetch(:four)                # error: KeyError

Хешове

итерация

numbers = {:one => :eins, :two => :zwei}
numbers.keys    # [:one, :two]
numbers.values  # [:eins, :zwei]

numbers.each { |pair| puts pair }
numbers.each { |key, value| puts key, value }

Хешове

разни методи

numbers = {1 => 2, 3 => 4}

numbers.has_key?(:three) # false
numbers.size             # 2
numbers.invert           # {2=>1, 4=>3}
numbers.merge({5 => 6})  # {1=>2, 3=>4, 5=>6}
numbers.to_a             # [[1, 2], [3, 4]]
Hash[1, 2, 3, 4]         # {1=>2, 3=>4}

Хешове

алтернативен синтаксис

Долните два реда произвеждат еднакви хешове. Второто е 1.9+ синтаксис и ще предпочитаме него по конвенция (когато може):

{:one => 1, :two => 2}
{one: 1, two: 2}

Има интересна врътка при извикването на методи, за която ще споменем малко по-натам.

Списъци и хешове

накратко

Въпроси