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

ЖАНРЫ

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

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]

Поделиться с друзьями: