Категории
Самые читаемые
Лучшие книги » Компьютеры и Интернет » Программирование » Программирование на языке Ruby - Хэл Фултон

Программирование на языке Ruby - Хэл Фултон

Читать онлайн Программирование на языке Ruby - Хэл Фултон

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 53 54 55 56 57 58 59 60 61 ... 156
Перейти на страницу:

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

а = [2, 3]

b = universe - а # Дополнение а = [1, 4, 5, 6]

Если считаете необходимым, можете определить и унарный оператор (например, - или ~ для выполнения этой операции.

Элементы множества можно перебирать, обходя массив. Единственная разница заключается в том, что элементы будут появляться в определенном порядке, а это может оказаться нежелательным. О том, как перебирать массив в случайном порядке, будет рассказано в разделе 8.1.18.

Наконец, иногда возникает необходимость вычислить степень множества. Это не что иное, как множество всех подмножеств данного множества (включая его само и пустое множество). Читатели, знакомые с дискретной математикой, в особенности с комбинаторикой, понимают, что число таких подмножеств равно 2n. Сгенерировать степень множества можно следующим образом:

class Array

 def powerset

  num = 2**size

  ps = Array.new(num, [])

  self.each_index do |i|

   a = 2**i

   b = 2**(i+1) — 1

   j = 0

   while j < num-1

    for j in j+a..j+b

     ps[j] += [self[i]]

    end

    j += 1

   end

  end

  ps

 end

end

x = [1, 2, 3]

y = x.powerset

# y равно:

#  [[], [1], [2], [1,2] , [3], [1,3], [2,3], [1,2,3]]

8.1.10. Рандомизация массива

Иногда нужно переставить элементы массива в случайном порядке. Первое, что приходит на ум, — тасование карточной колоды, но есть и другие применения — например, случайная сортировка списка вопросов.

Для решения этой задачи пригодится метод rand из модуля Kernel. Ниже показан один из возможных способов:

class Array

 def randomize

  self.sort_by { rand } # Сортировать по ключу, являющемуся

 end                    # случайным числом.

 def randomize!

  self.replace(self.randomize)

 end

end

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

y = x.randomize # [3, 2, 4, 1, 5]

x.randomize!    # x равно [3, 5, 4, 2]

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

Выбрать случайный элемент массива (не запрещая дубликатов) можно так:

class Array

 def pick_random

  self[rand(self.length)]

 end

end

Наконец, не стоит забывать, что метод rand позволяет сгенерировать предсказуемую последовательность (например, для тестирования), если затравить алгоритм известным значением с помощью метода srand (см. раздел 5.28).

8.1.11. Многомерные массивы

Если для численного анализа вам нужны многомерные массивы, то в архиве приложений Ruby есть прекрасная библиотека NArray, которую написал Масахиро Танака (Masahiro Tanaka). Если необходим аппарат для работы с матрицами, обратитесь к стандартной библиотеке matrix.rb, которая была упомянута в разделе 5.10.

В следующем примере показан способ работы с многомерными массивами за счет перегрузки методов [] и []= для отображения элементов на вложенный массив. Представленный класс Array3 обеспечивает рудиментарные операции с трехмерными массивами, но он далеко не полон:

class Array3

 def initialize

  @store = [[[]]]

 end

 def [](a,b,c)

  if @store[a]==nil ||

   @store[a][b]==nil ||

   @store[a][b][c]==nil

   return nil

  else

   return @store[a][b][c]

  end

 end

 def []=(a,b,c,x)

  @store[a] = [[]] if @store[a]==nil

  @store[a][b] = [] if @store[a][b]==nil

  @store[a][b][с] = x

 end

end

x = Array3.new

x[0,0,0] = 5

x[0,0,1] = 6

x[1,2,31 = 99

puts x[1,2,3]

Единственное, чего мы реально добились, — так это удобного использования запятой в обозначении [x,y,z] вместо употребляемой в языке С нотации [x][у][z]. Если C-подобная нотация вас устраивает, можете просто воспользоваться вложенными массивами Ruby. Еще одно мелкое достоинство — предотвращение ситуации, когда объектом, от имени которого вызывается оператор [], оказывается nil.

8.1.12. Нахождение элементов, принадлежащих одному массиву и не принадлежащих другому

В Ruby эта задача решается проще, чем во многих других языках. Нужно просто вычислить «разность множеств»:

text = %w[the magic words are squeamish ossifrage]

dictionary = %w[an are magic the them these words]

# Найти неправильно написанные слова

unknown = text - dictionary # ["squeamish", "ossifrage"]

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

Метод collect из модуля Enumerable часто позволяет сэкономить время и силы. Тем, кто привык к языку Smalltalk, он покажется интуитивно очевидным в большей степени, чем программистам на С.

Этот метод просто воздействует неким произвольным образом на каждый элемент массива, порождая в результате новый массив. Иными словами, он «отображает» один массив на другой (отсюда и синоним map).

x = %w[alpha bravo charlie delta echo foxtrot]

# Получить начальные буквы.

a = x.collect (|w| w[0..0]}  # %w[a b с d e f]

# Получить длины строк.

b = x.collect {|w| w.length} # [5, 5, 7, 5, 4, 7]

# map - просто синоним.

с = x.map {|w| w.length}     # [5, 5, 7, 5, 4, 7]

Имеется также вариант collect! (или map!) для модификации на месте.

x.collect! {|w| w.upcase}

# x равно %w[ALPHA BRAVO CHARLIE DELTA ECHO FOXTROT]

x.map! {|w| w.reverse}

# x равно %w[AHPLA OVARB EILRAHC ATLED OHCE TORTXOF]

8.1.14. Удаление из массива элементов равных nil

Метод compact (и его вариант compact! для модификации на месте) удаляет из массива элементы равные nil, оставляя все остальные без изменения:

a = [1, 2, nil, 3, nil, 4, 5]

b = a.compact # [1, 2, 3, 4, 5]

a.compact!    # а равно [1, 2, 3, 4, 5]

8.1.15. Удаление заданных элементов из массива

В Ruby легко удалить элементы из массива - для этого даже существует много способов. Чтобы удалить элемент с известным индексом, достаточно вызвать метод delete_at:

a = [10, 12, 14, 16, 18]

a.delete_at(3) # Возвращает 16.

# а равно [10, 12, 14, 18]

a.delete_at(9) # Возвращает nil {вне диапазона).

Все элементы с заданным значением поможет удалить метод delete. Он возвращает значения удаленных элементов или nil, если искомый элемент не найден:

b = %w(spam spam bacon spam eggs ham spam)

b.delete("spam") # Возвращает "spam"

# b равно ["bacon", "eggs", "ham"]

b.delete("caviar") # Возвращает nil

Метод delete принимает также блок. Это не вполне согласуется с интуицией; если объект не найден, происходит вычисление блока (при этом могут выполняться разнообразные операции) и возвращается вычисленное значение.

с = ["alpha", "beta", "gamma", "delta"]

c.delete("delta") { "Nonexistent" }

# Возвращается "delta" (блок не вычисляется).

с.delete("omega") { "Nonexistent" }

# Возвращается "Nonexistent".

Метод delete_if передает каждый элемент массива в блок и удаляет те элементы, для которых вычисление блока дает true. Примерно так же ведет себя метод reject! с тем отличием, что последний может возвращать nil, когда массив не изменяется.

email = ["job offers", "greetings", "spam", "news items"]

# Удалить слова из четырех букв

email.delete_if {|x| x.length==4 }

# email равно ["job offers", "greetings", "news items"]

Метод slice! получает доступ к тем же элементам, что и slice, но, помимо возврата их значений, еще и удаляет из массива:

x = [0, 2, 4, 6, 8, 10, 12, 14, 16]

а = x.slice!(2)    # 4

# x is now [0, 2, 6, 8, 10, 12, 14, 16]

b = x.slice!(2,3)  # [6, 8, 10]

# x is now [0, 2, 12, 14, 16]

с = x.slice!(2..3) # [12, 14]

# x is now [0, 2, 16]

Для удаления элементов из массива можно также пользоваться методами shift и pop (дополнительную информацию об их исходном предназначении вы найдете в разделе 9.2).

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

x.рор   # Удалить последний элемент.

# x is now [1, 2, 3, 4]

x.shift # Удалить первый элемент.

# x is now [2, 3, 4]

Метод reject принимает блок и формирует новый массив без тех элементов, для которых блок возвращает true:

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

odd = arr.reject {|x| x % 2 == 0 } # [1,3,5,7]

Наконец, метод clear удаляет из массива все элементы. Это эквивалентно присваиванию переменной пустого массива, но чуть-чуть эффективнее:

1 ... 53 54 55 56 57 58 59 60 61 ... 156
Перейти на страницу:
На этой странице вы можете бесплатно скачать Программирование на языке Ruby - Хэл Фултон торрент бесплатно.
Комментарии