0

I'm struggling trying to convert this array:

arr = [
  {:type=>"Type One",
   :data=>[
     {'Wed, 01 Apr 2020'=>11.0},
     {'Fri, 01 May 2020'=>0.0},
     {'Mon, 01 Jun 2020'=>1081.5},
     {'Wed, 01 Jul 2020'=>0.0}
   ]
  },
  {:type=>"Type Two",
   :data=>[
     {'Wed, 01 Apr 2020'=>19.55},
     {'Fri, 01 May 2020'=>0.0},
     {'Mon, 01 Jun 2020'=>68.56},
     {'Wed, 01 Jul 2020'=>200.0}
   ]
  }
] 

to this array:

[{:type=>"Type One",
  :data=>{'Wed, 01 Apr 2020'=>11.0, 'Fri, 01 May 2020'=>0.0,
          'Mon, 01 Jun 2020'=>1081.5, 'Wed, 01 Jul 2020'=>0.0}},
 {:type=>"Type Two",
  :data=>{'Wed, 01 Apr 2020'=>19.55, 'Fri, 01 May 2020'=>0.0,
          'Mon, 01 Jun 2020'=>68.56, 'Wed, 01 Jul 2020'=>200.0}}]

As you see, I wish to convert the value of :data in each hash in arr from an array of single-key hashes to a single hash.

2
  • 4
    I recommend that your examples be something that can be copied and pasted directly into an IRB console. These examples cannot. They should also be pretty-printed to make it clear what change you're trying to make. Commented Jul 8, 2020 at 19:24
  • What have you tried? Where did you get stuck? What did you do to get unstuck? Why did that fail? You need to show the code you have problems with, Stack Overflow is not a code-writing service. Commented Jul 9, 2020 at 5:12

2 Answers 2

2
arr.map do |h|
  h.each_with_object({}) do |(k,v),g|
    g[k] = (k == :data) ? v.reduce(:merge) : v
  end
end
  #=> [{:type=>"Type One",
  #     :data=>{'Wed, 01 Apr 2020'=>11.0, 'Fri, 01 May 2020'=>0.0,
  #             'Mon, 01 Jun 2020'=>1081.5, 'Wed, 01 Jul 2020'=>0.0}},
  #    {:type=>"Type Two",
  #     :data=>{'Wed, 01 Apr 2020'=>19.55, 'Fri, 01 May 2020'=>0.0,
  #             'Mon, 01 Jun 2020'=>68.56, 'Wed, 01 Jul 2020'=>200.0}}]

If, for example,

v = [{'Wed, 01 Apr 2020'=>11.0}, {'Fri, 01 May 2020'=>0.0},
     {'Mon, 01 Jun 2020'=>1081.5}, {'Wed, 01 Jul 2020'=>0.0}]

then

v.reduce(:merge)
  #=> {"Wed, 01 Apr 2020"=>11.0, "Fri, 01 May 2020"=>0.0,
  #    "Mon, 01 Jun 2020"=>1081.5, "Wed, 01 Jul 2020"=>0.0}

This can be thought as shorthand for:

v.reduce { |h, g| h.merge(g) }

See Enumerable#reduce (aka inject) and Hash#merge.

Sign up to request clarification or add additional context in comments.

Comments

1

It appears what you are after is to combine an array of little hashes into a single hash. You can use the .inject() Array method to do that:

a = [{Wed, 01 Apr 2020=>11.0}, {Fri, 01 May 2020=>0.0}]}
a.inject(:merge!)
=> {Wed, 01 Apr 2020=>11.0, Fri, 01 May 2020=>0.0}

Inject combines all the elements in an array using a method (or block). Passing :merge! to it causes each iteration to destructively merge the hash so you don't have the waste of creating little hash copies as it goes.

So in your case you'd iterate over the outer array and use .inject to massage the data array into a hash.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.