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

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

Жанры

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

8.1.9. Массивы как математические множества

В большинстве языков множества напрямую не реализованы (Pascal составляет исключение). Но массивы в Ruby обладают некоторыми свойствами, которые позволяют использовать их как множества. В данном разделе мы рассмотрим эти свойства и добавим свои собственные.

В последних версиях Ruby стандартная библиотека содержит класс

Set
. Если вам приходится часто иметь дело с множествами, подумайте об использовании объектов
Set
вместо массивов. Этот класс рассмотрен в главе 9.

Массив нельзя назвать идеальным средством для представления

множества, поскольку он может содержать дубликаты. Если вы хотите трактовать массив как множество, то дубликаты можно удалить (с помощью метода
uniq
или
uniq!
).

Над множествами производятся две основные операции: объединение и пересечение. Для этого применяются операторы

|
(или) и
&
(и) соответственно. Поскольку множество по определению не содержит дубликатов, то повторяющиеся элементы удаляются (вопреки ожиданиям тех, кому доводилось работать с объединением и пересечением массивов в других языках).

а = [1, 2, 3, 4, 5]

b = [3, 4, 5, 6, 7]

с = a | b # [1, 2, 3, 4, 5, 6, 7]

d = а & b # [3,4,5]

# Дубликаты удаляются...

e = [1, 2, 2, 3, 4]

f = [2, 2, 3, 4, 5]

g = e & f # [2; 3, 4]

Для объединения множеств можно использовать и оператор конкатенации (

+
), но он не удаляет дубликаты.

Метод

соответствует операции «разность множеств»; результатом является множество, куда входят те элементы первого множества, которые не являются элементами второго (см. раздел 8.1.12).

а = [1, 2, 3, 4, 5]

b = [4, 5, 6, 7]

с = а - b # [1, 2, 3]

# Отметим, что наличие элементов 6 and 7 не отражается на результате.

Для «аккумулирования» множеств можно применять оператор

|=
; как и следовало ожидать,
а |= b
— то же самое, что
а = а | b
. Аналогичным образом оператор
&=
последовательно «сужает» множество.

Для массивов не определена операция ИСКЛЮЧАЮЩЕЕ ИЛИ, но мы можем без труда реализовать ее. В терминах теории множеств она соответствует выборке тех элементов, которые входят в объединение двух множеств, но не входят в их пересечение.

class Array

 def ^(other)

(self | other) - (self & other)

 end

end

x = [1, 2, 3, 4, 5]

y = [3, 4, 5, 6, 7]

z = x ^ y # [1, 2, 6, 7]

Чтобы проверить, входит ли некий элемент в множество, пользуйтесь методом

include?
или
member?
(синоним, подмешанный из модуля
Comparable
):

x = [1, 2, 3]

if x.include? 2

 puts "yes" #
Печатается "yes"

else

 puts "no"

end

Конечно, это некоторое отступление от канонов математики, где для обозначения принадлежности множеству применяется символ, похожий на греческую букву эпсилон. Отступление в том смысле, что множество находится слева, а не справа от оператора, то есть мы спрашиваем не «принадлежит ли данный элемент множеству», а «содержит ли множество данный элемент».

Многим это безразлично. Но привыкшие к языку Pascal или Python (или впитавшие математический формализм с молоком матери) хотели бы, чтобы было по-другому. Такую возможность мы реализуем в следующем фрагменте:

class Object

 def in(other)

other.include? self

 end

end

x = [1, 2, 3]

if 2.in x

 puts "yes" # Печатается "yes"

else

 puts "no"

end

Лично я отправил запрос на изменение Ruby (RCR 241) с предложением ввести в язык оператор

in
. Он должен походить на одноименный оператор в языках Pascal, Python и даже SQL.

У этой идеи есть свои достоинства (к тому же

in
— уже зарезервированное слово), но единодушного одобрения она не получила. Может быть, оператор in появится в Ruby, а может, и нет.

Теперь обратимся к подмножествам и надмножествам. Как определить, является ли данное множество подмножеством или надмножеством другого? Встроенных методов для этого нет, но мы можем поступить следующим образом:

class Array

 def subset?(other)

self.each do |x|

if !(other.include? x)

return false

end

end

true

 end

 def superset?(other)

other.subset?(self)

 end

end

a = [1, 2, 3, 4]

b = [2, 3]

с = [2, 3, 4, 5]

flag1 = c.subset? a # false

flag2 = b.subset? a # true

flag3 = c.superset? b # true

Обратите внимание: мы выбрали «естественный» порядок, то есть задаем вопрос

x.subset?у
— «является ли
x
подмножеством
у?
», а не наоборот.

Для распознавания пустого множества достаточно проверить, пуст ли массив. Это делает метод

empty?
.

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

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

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

Вперед в прошлое 8

Ратманов Денис
8. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 8

Авиатор: назад в СССР

Дорин Михаил
1. Авиатор
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Авиатор: назад в СССР

Сирота

Ланцов Михаил Алексеевич
1. Помещик
Фантастика:
альтернативная история
5.71
рейтинг книги
Сирота

Цикл романов "Целитель". Компиляция. Книги 1-17

Большаков Валерий Петрович
Целитель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Цикл романов Целитель. Компиляция. Книги 1-17

Наследник с Меткой Охотника

Тарс Элиан
1. Десять Принцев Российской Империи
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Наследник с Меткой Охотника

Запасная дочь

Зика Натаэль
Фантастика:
фэнтези
6.40
рейтинг книги
Запасная дочь

Зодчий. Книга II

Погуляй Юрий Александрович
2. Зодчий Империи
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Зодчий. Книга II

Кодекс Крови. Книга ХVII

Борзых М.
17. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХVII

По осколкам твоего сердца

Джейн Анна
2. Хулиган и новенькая
Любовные романы:
современные любовные романы
5.56
рейтинг книги
По осколкам твоего сердца

Черный Маг Императора 7 (CИ)

Герда Александр
7. Черный маг императора
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 7 (CИ)

Романов. Том 1 и Том 2

Кощеев Владимир
1. Романов
Фантастика:
фэнтези
попаданцы
альтернативная история
5.25
рейтинг книги
Романов. Том 1 и Том 2

Тринадцатый

NikL
1. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
6.80
рейтинг книги
Тринадцатый

Камень. Книга 4

Минин Станислав
4. Камень
Фантастика:
боевая фантастика
7.77
рейтинг книги
Камень. Книга 4