arr = [
{day: 'Monday', class: 1, name: 'X'},
{day: 'Monday', class: 2, name: 'Y'},
{day: 'Tuesday', class: 1, name: 'Z'},
{day: 'Monday', class: 1, name: 'T'}
]
Один из способов получения желаемого хэша заключается в использовании формы Hash#update (он же объединить!), Который использует блок для определения значений ключей, которые присутствуют в обеих хешей быть объединены. Здесь это делается дважды, сначала, когда значения :day
одинаковы, то для каждого такого вхождения, когда значения :class
одинаковы (при заданном значении :day
).
arr.each_with_object({}) { |g,h|
h.update(g[:day]=>{ g[:class].to_s=>[{name: g[:name] }] }) { |_,h1,h2|
h1.update(h2) { |_,p,q| p+q } } }
#=> {"Monday" =>{"1"=>[{:name=>"X"}, {:name=>"T"}], "2"=>[{:name=>"Y"}]},
# "Tuesday"=>{"1"=>[{:name=>"Z"}]}}
Этапы заключаются в следующем.
enum = arr.each_with_object({})
#=> #<Enumerator: [{:day=>"Monday", :class=>1, :name=>"X"},
# {:day=>"Monday", :class=>2, :name=>"Y"},
# {:day=>"Tuesday", :class=>1, :name=>"Z"},
# {:day=>"Monday", :class=>1, :name=>"T"}]:each_with_object({})>
Мы можем увидеть значения, которые будут генерироваться этим интервьюером путем преобразования его в массив:
enum.to_a
#=> [[{:day=>"Monday", :class=>1, :name=>"X"}, {}],
# [{:day=>"Monday", :class=>2, :name=>"Y"}, {}],
# [{:day=>"Tuesday", :class=>1, :name=>"Z"}, {}],
# [{:day=>"Monday", :class=>1, :name=>"T"}, {}]]
Пустой хеш в каждом массиве является хэш строится и возвращается. Он изначально пуст, но будет частично сформирован по мере обработки каждого элемента из enum
.
Первый элемент enum
передается к блоку (по Enumerator#each) и блок-переменные присваиваются с помощью параллельного назначения (Somtimes называется множественное присваивание):
g,h = enum.next
#=> [{:day=>"Monday", :class=>1, :name=>"X"}, {}]
g #=> {:day=>"Monday", :class=>1, :name=>"X"}
h #=> {}
теперь выполнение блока Расчет:
h.update(g[:day]=>{ g[:class].to_s=>[{name: g[:name] }] })
#=> {}.update("Monday"=>{ "1"=>[{name: "X"}] })
#=> {"Monday"=>{"1"=>[{:name=>"X"}]}}
Эта операция возвращает обновленное значение h
, хэш будет построен.
Обратите внимание, что update
«s аргумент
"Monday"=>{ "1"=>[{name: "X"}] }
представляет собой сокращенную
{ "Monday"=>{ "1"=>[{name: "X"}] } }
Поскольку ключ "Monday"
не присутствовал в обоих хешей быть слиты (h
не было ключей), блок
{ |_,h1,h2| h1.update(h2) { |_,p,q| p+q } } }
не использовался для определения ermine значение "Monday"
.
Теперь следующее значение enum
передается в блок и блок переменных назначаются:
g,h = enum.next
#=> [{:day=>"Monday", :class=>2, :name=>"Y"},
# {"Monday"=>{"1"=>[{:name=>"X"}]}}]
g #=> {:day=>"Monday", :class=>2, :name=>"Y"}
h #=> {"Monday"=>{"1"=>[{:name=>"X"}]}}
Обратите внимание, что h
была обновлена. Теперь мы выполняем расчет блока:
h.update(g[:day]=>{ g[:class].to_s=>[{name: g[:name] }] })
# {"Monday"=>{"1"=>[{:name=>"X"}]}}.update("Monday"=>{ "2"=>[{name: "Y"}] })
Оба хэша, объединившиеся, используют ключ «Понедельник». Поэтому мы должны использовать блок, чтобы определить, слитый значение «Понедельник»:
{ |k,h1,h2| h1.update(h2) { |m,p,q| p+q } } }
#=> {"1"=>[{:name=>"X"}]}.update("2"=>[{name: "Y"}])
#=> {"1"=>[{:name=>"X"}], "2"=>[{:name=>"Y"}]}
ВИДЕТЬ док для update
для объяснения блока переменных k
, h1
и h2
для наружного update
и m
, p
и q
для внутреннего update
. k
и m
- значения общего ключа. Поскольку они не используются в блочных вычислениях, я заменил их символами подчеркивания, что является обычной практикой.
Итак:
h #=> { "Monday" => { "1"=>[{ :name=>"X" }], "2"=>[{ :name=>"Y"}] } }
До этой операции хэш h["Monday]
еще не было ключа 2
, поэтому второй update
не требует использования блока
{ |_,p,q| p+q }
Этот блок однако, когда последний элемент enum
слит в h
, так как значения обоих :day
и :class
одинаковы для двух га shes сливается.
Остальные вычисления аналогичны.
Вы не хотите, чтобы 'groupedArray ['Monday'] => {'1' => [{name: 'X'}, {name: 'T'}], '2' => [ {name: 'Y'}]} '? Я ожидаю, что это отразится на downvotes. –
Да, это то, чего я хочу. Не заметил неправильных скобок, извините – Dragos
Просто хотел узнать, есть ли более короткий способ сделать это. – Dragos