Это один из способов сделать это:
alphabet = "AABBBCCCCDDDDDEFGHIJKLMNOPQRSTUVWXYZZZZZZ"
h = alphabet.each_char.
with_index(1).
group_by(&:first).
transform_values { |a| a.map(&:last) }
#=> {"A"=>[1, 2], "B"=>[3, 4, 5], "C"=>[6, 7, 8, 9],
# "D"=>[10, 11, 12, 13, 14], "E"=>[15], "F"=>[16], "G"=>[17],
# "H"=>[18], "I"=>[19], "J"=>[20], "K"=>[21], "L"=>[22], "M"=>[23],
# "N"=>[24], "O"=>[25], "P"=>[26], "Q"=>[27], "R"=>[28], "S"=>[29],
# "T"=>[30], "U"=>[31], "V"=>[32], "W"=>[33], "X"=>[34], "Y"=>[35],
# "Z"=>[36, 37, 38, 39, 40, 41]}
c = 'Z'
puts "All the #{c}'s: #{h[c]}"
All the Z's: [36, 37, 38, 39, 40, 41]
Шаги следующие:
a = alphabet.each_char
#=> #<Enumerator:"AABBB...ZZZZZZ":each_char>
b = a.with_index(1)
#=> #<Enumerator: #<Enumerator: "AABBB...ZZZZZZ":each_char>:with_index(1)>
c = b.group_by(&:first)
#=> {"A"=>[["A", 1], ["A", 2]],
# "B"=>[["B", 3], ["B", 4], ["B", 5]],
# ...
# "Z"=>[["Z", 36], ["Z", 37], ["Z", 38], ["Z", 39], ["Z", 40],
# ["Z", 41]]}
b.group_by(&:first)
более или менее сокращенно для:
c = b.group_by { |c,i| c }
Наконец:
c.transform_values { |a| a.map(&:last) }
#=> <as above>
Примечание:
a.next #=> "A"
a.next #=> "A"
a.next #=> "A"
a.next #=> "B"
...
и
b.next #=> ["A", 1]
b.next #=> ["A", 2]
b.next #=> ["B", 3]
b.next #=> ["B", 4]
...
Элементы, сгенерированные перечислителем b
, передаются в Блок group_by
, { |c,i| c }
и переменные блока присваиваются их значениям. Например:
b.rewind
c, i = b.next #=> ["A", 1]
c #=> "A"
i #=> 1
См. Enumerator # with_index , Enumerable # group_by и Hash # transform_values , Enumerator # next и Перечислитель # перемотка .