Вот один из способов среди многих:
class Array
def find_indices(val)
each_with_index.select { |e,i| e == val }.map(&:last)
end
end
[1,3,5,2,6,3,5,7,8,3,2,4].find_indices(3)
#=> [1, 5, 9]
Вот что происходит. Сначала val
устанавливается равным 3
. Затем метод Enumerable#each_with_index отправляется на номер self
, поскольку не предоставляется явный приемник. self
равно массив, который вы можете легко подтвердить, добавив строку:
puts "self = #{self}"
к началу метода find_indices
. Теперь вы получите:
[1,3,5,2,6,3,5,7,8,3,2,4].find_indices(3)
# self = [1, 3, 5, 2, 6, 3, 5, 7, 8, 3, 2, 4]
#=> [1, 5, 9]
Как видно из документации, так как each_with_index
не дается блок, перечислитель возвращается:
enum = [1,3,5,2,6,3,5,7,8,3,2,4].each_with_index
#=> #<Enumerator: [1, 3, 5, 2, 6, 3, 5, 7, 8, 3, 2, 4]:each_with_index>
Чтобы проверить элементы enum
, преобразовать его в массив:
enum.to_a
#=> [[1, 0], [3, 1], [5, 2], [2, 3], [6, 4], [3, 5],
# [5, 6], [7, 7], [8, 8], [3, 9], [2, 10], [4, 11]]
Далее мы посылаем метод Enumerable#select к enum
:
new_enum = enum.select
#=> #<Enumerator: #<Enumerator: [1, 3, 5, 2, 6, 3, 5, 7,
# 8, 3, 2, 4]:each_with_index>:select>
new_enum.to_a
#=> [[1, 0], [3, 1], [5, 2], [2, 3], [6, 4], [3, 5],
# [5, 6], [7, 7], [8, 8], [3, 9], [2, 10], [4, 11]]
Обратите внимание на описание new_enum
. Вы можете счесть это соображением как «составной перечислитель», но это перечислитель.
Теперь мы даем select
блок, поэтому каждый элемент new_enum
будет передан блоку. Первый элемент передается в [1, 0]
и назначение блоков переменных производится:
e, i = [1, 0]
e #=> 1
i #=> 0
Мы находим, что (e == val) #=> (1 == 3) #=> false
, поэтому элемент не выбран. Следующий элемент, переданный блоку, [3, 1]
, вызывает (3 == 3) #=> true
, поэтому выбирается [3, 1]
.
Получаем:
a = new_enum.each { |e,i| e == val }
#=> [[3, 1], [3, 5], [3, 9]]
Как это индексы для этих значений, которые мы хотим, мы извлекая их отображения:
a.map(&:last)
#=> [1, 5, 9]
что эквивалентно:
a.map { |e| e.last }
Эта последняя операция также может быть выполнена таким образом:
a.transpose.last
Еще один простой способ сделать это следующим образом.
class Array
def find_indices(val)
index = 0
each_with_object([]) do |e,a|
(a << index) if e == val
index += 1
end
end
end
[1,3,5,2,6,3,5,7,8,3,2,4].find_indices(3)
#=> [1, 5, 9]
Вы должны опубликовать код, который показывает, что вы пробовали. –
Большинство методов, которые помогут в этом, находятся в модуле Enumerable (а массивы перечислены). –
Этот вопрос вполне может стать закрытым. Надеюсь нет. Прочитайте рекомендации по [как спросить] (http://stackoverflow.com/help/how-to-ask) и предоставьте код, который вы укажете, где вы «пытались решить эту проблему», чтобы вы могли получить обратную связь, которая имеет отношение к вашему вопросу, и помочь другим, находящимся в вашей ситуации. – vgoff