Чтение онлайн

на главную - закладки

Жанры

Программирование на языке Ruby
Шрифт:

В следующем немного более сложном примере мы находим самое длинное слово в списке:

words = %w[ alpha beta gamma delta epsilon eta theta ]

longest_word = words.inject do |best,w|

 w.length > best.length ? w : best

end

# Возвращается значение "epsilon".

8.3.2. Кванторы

Кванторы

any?
и
all?
появились в версии Ruby 1.8, чтобы было проще проверять некоторые свойства набора. Оба квантора принимают в качестве параметр блок (который должен возвращать значение
true
или
false
).

Nums = [1,3,5,8,9]

# Есть ли среди чисел четные?

flag1 = nums.any? {|x| x % 2 == 0 } # true

# Все ли числа четные?

flag2 = nums.all? {|x| x % 2 == 0 } # false

Если блок не задан, то просто проверяется значение истинности каждого элемента. Иными словами, неявно добавляется блок

{|x| x }
.

flag1 = list.all? # list не содержит ни одного false или nil.

flag1 = list.any? # list содержит хотя бы одно истинное значение

# не nil и не false).

8.3.3. Метод partition

Как говорится, «в мире есть два сорта людей: те, что делят людей по сортам, и те, что не делят». Метод

partition
относится не к людям (хотя мы можем представить их в Ruby как объекты), но тоже делит набор на две части.

Если при вызове

partition
задан блок, то он вычисляется для каждого элемента набора. В результате создаются два массива: в первый попадают элементы, для которых блок вернул значение
true
, во второй — все остальные. Метод возвращает массив, двумя элементами которого являются эти массивы.

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]

odd_even = nums.partition {|x| x % 2 == 1 }

# [[1,3,5,7,9],[2,3,4,6,8]]

under5 = nums.partition {|x| x < 5 }

# [[1,2,3,4],[5,6,7,8,9]]

squares = nums.partition {|x| Math.sqrt(x).to_i**2 == x }

# [[1,4,9], [2,3,5,6,7,8]]

Если нужно разбить набор больше чем на две группы, придется написать собственный метод. Я назвал его

classify
по аналогии с методом из класса
Set
.

module Enumerable

 def classify(&block)

hash = {}

self.each do |x|

result = block.call(x)

(hashfresult] ||= []) << x

end

hash

 end

end

nums = [1,2,3,4,5,6,7,8,9]

mod3 = nums.classify {|x| x % 3 }

# { 0=>[3,6,9], 1=>[1,4,7], 2=>[2,5,8] }

words = %w( area arboreal brick estrous clear donor ether filial

patina ]

vowels = words.classify {|x| x.count("aeiou") }

# {1=>["brick"], 2=>["clear", "donor", "ether"],

# 3=>["area", "estrous", "filial", "patina"], 4=>["arboreal"]}

initials = words.classify {|x| x[0..0] }

# {"a"=>["area", "arboreal"], "b"=>["brick"], "c"=>["clear"],

# "d"=>["donor"], "p"=>["patina"], "e"=>["estrous", "ether"],

# "f"=>["filial"]}

8.3.4. Обход с группировкой

До сих пор мы обходили список по одному элементу за раз. Но иногда желательно на каждой итерации анализировать по два, три или более элементов.

Итератор

each_slice
принимает в качестве параметра число n, равное числу просматриваемых на каждой итерации элементов. (Для работы с ним нужна библиотека
enumerator
.) Если не осталось достаточного количества элементов, размер последнего фрагмента будет меньше.

require 'enumerator'

arr = [1,2,3,4,5,6,7,8,9,10]

arr.each_slice(3) do |triple|

 puts triple.join(",")

end

# Выводится:

# 1,2,3

# 4,5,6

# 7,8,9

# 10

Имеется также итератор

each_cons
, который позволяет обходить набор методом «скользящего окна» заданного размера. (Если название кажется вам странным, знайте, что это наследие языка Lisp.) В таком случае фрагменты всегда будут иметь одинаковый размер.

require 'enumerator'

arr = [1,2,3,4,5,6,7,8,9,10]

arr.each_cons(3) do |triple|

 puts triple.join(",")

end

# Выводится:

# 1,2,3

# 2,3,4

# 3,4,5

# 4,5,6

# 5,6,7

# 6,7,8

# 7,8,9

# 8,9,10

8.3.5. Преобразование в массив или множество

Каждая перечисляемая структура теоретически может быть тривиально преобразована в массив (методом

to_a
). Например, такое преобразование для хэша дает вложенный массив пар:

hash = {1=>2, 3=>4, 5=>6}

arr = hash.to_a # [[5, 6], [1, 2], [3, 4]]

Синонимом

to_a
является метод
entries
.

Если была затребована библиотека

set
, становится доступен также метод
to_set
. Дополнительная информация о множествах приведена в разделе 9.1.

Поделиться:
Популярные книги

Перезагрузка или Back in the USSR. Дилогия

Марченко Геннадий Борисович
Фантастика:
попаданцы
альтернативная история
6.83
рейтинг книги
Перезагрузка или Back in the USSR. Дилогия

Ученик

Первухин Андрей Евгеньевич
1. Ученик
Фантастика:
фэнтези
6.27
рейтинг книги
Ученик

Начало шторма

Мазуров Дмитрий
9. Громовая поступь
Фантастика:
фэнтези
рпг
5.75
рейтинг книги
Начало шторма

Боярич Морозов

Шелег Дмитрий Витальевич
3. Наследник старого рода
Фантастика:
героическая фантастика
боевая фантастика
альтернативная история
7.12
рейтинг книги
Боярич Морозов

Эпоха Опустошителя. Том I

Павлов Вел
1. Вечное Ристалище
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Эпоха Опустошителя. Том I

Эволюционер из трущоб. Том 10

Панарин Антон
10. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 10

Изгой. Трилогия

Михайлов Дем Алексеевич
Изгой
Фантастика:
фэнтези
8.45
рейтинг книги
Изгой. Трилогия

Осколки чести

Буджолд Лоис Макмастер
1. Сага о Форкосиганах
Фантастика:
космическая фантастика
9.34
рейтинг книги
Осколки чести

Эрсус. Инферно

Павлов Вел
3. Стезя Эрсуса
Фантастика:
фэнтези
5.00
рейтинг книги
Эрсус. Инферно

Обломов

Гончаров Иван Александрович
Проза:
классическая проза
русская классическая проза
5.00
рейтинг книги
Обломов

Наномашины, ученик! Том 6

Новиков Николай Васильевич
6. Первый среди карапузов
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Наномашины, ученик! Том 6

Неучтенный элемент. Том 3

NikL
3. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 3

Бессонница (др.перевод)

Кинг Стивен
17. Темная Башня
Фантастика:
ужасы и мистика
8.33
рейтинг книги
Бессонница (др.перевод)

Кодекс Охотника. Книга XXXII

Винокуров Юрий
32. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXII