FName = 'test'
str = "1,Foo,20,Smith, 40,John,55"
File.write(FName, str)
#=> 26
base, *arr = File.read(FName).
split(/\s*,\s*/)
enum = (base.to_i).step
arr.each_slice(2).
with_object({}) {|pair,h| h[enum.next]=pair}
#=> {1=>["Foo", "20"], 2=>["Smith", "40"],
# 3=>["John", "55"]}
Шаги следующие:
s = File.read(FName)
#=> "1,Foo,20,Smith, 40,John,55"
base, *arr = s.split(/\s*,\s*/)
#=> ["1", "Foo", "20", "Smith", "40", "John", "55"]
base
#=> "1"
arr
#=> ["Foo", "20", "Smith", "40", "John", "55"]
a = base.to_i
#=> 1
Я предполагаю, что ключи должны быть последовательными целыми числами, начинающимися с a #=> 1
.
enum = a.step
#=> (1.step)
enum.next
#=> 1
enum.next
#=> 2
enum.next
#=> 3
Продолжение,
enum = a.step
b = arr.each_slice(2)
#=> #<Enumerator: ["Foo", "20", "Smith", "40", "John", "55"]:each_slice(2)>
Примечание. Мне нужно было переопределить enum
(или выполнить enum.rewind
) для его повторной инициализации.Мы можем видеть элементы, которые будут сгенерированы этим перечислителем, преобразовав его в массив.
b.to_a
#=> [["Foo", "20"], ["Smith", "40"], ["John", "55"]]
Продолжение,
c = b.with_object({})
#=> #<Enumerator: #<Enumerator: ["Foo", "20", "Smith", "40", "John", "55"]
# :each_slice(2)>:with_object({})>
c.to_a
#=> [[["Foo", "20"], {}], [["Smith", "40"], {}], [["John", "55"], {}]]
Теперь пустые хеши будут создаваться по мере выполнения вычислений..
c.each {|pair,h| h[enum.next]=pair}
#=> {1=>["Foo", "20"], 2=>["Smith", "40"], 3=>["John", "55"]}
Чтобы увидеть, как выполняется последний шаг, each
первоначально направляет перечислитель c
для генерации первого значения, которое он передает блоку.Переменные блока присваиваются этому значению, и выполняется вычисление блока.
enum = a.step
b = arr.each_slice(2)
c = b.with_object({})
pair, h = c.next
#=> [["Foo", "20"], {}]
pair
#=> ["Foo", "20"]
h #=> {}
h[enum.next]=pair
#=> ["Foo", "20"]
Теперь
h#=> {1=>["Foo", "20"]}
Вычисления аналогичны для оставшихся двух элементов, сгенерированных перечислителем c
.
См. IO :: write , IO :: read , Числовой # шаг , Enumerable # each_slice , Перечислитель # with_object , Перечислитель # следующий и Перечислитель # перемотка .write
и read
отвечают на File
, поскольку File
является подклассом IO
(File.superclass #=> IO
).Аргумент split
, регулярное выражение /\s*,\s*/
, вызывает разделение строки на запятые вместе с любыми пробелами, которые окружают запятые.Преобразование [["Foo", "20"], {}]
в pair
и h
является продуктом Разложение массива .