0

Trying to build a json out of Ruby hash

require 'json'
temp_rides = {"rides": {}}
rides = {:lyft => "car", :scoot => "scooter", :blade => "helicopter"}
rides.each do |key, value|
 temp_rides["rides"].push({"key" => "value"})
 puts temp_rides
end

apparently it fails with undefined methodpush'` I believe I need to load the json object before append (based on my python background).

I am looking for a output something like this

{
    "rides": {
        "lyft": {
            "type": "car"
        },
        "scoot": {
            "type": "scooter"
        },
        "blade": {
            "type": "helicopter"
        }
    }
}
5
  • temp_rides["rides"].merge({"key" => "value"})? Commented Oct 18, 2019 at 1:00
  • That's going to require some work as your keys are labelled rideN, but not very consistently. type vs. type2 for instance. Commented Oct 18, 2019 at 1:07
  • @Fabio undefined method `merge' Commented Oct 18, 2019 at 1:48
  • @tadman thanks for the input, true not consistent. I just fixed it. Commented Oct 18, 2019 at 1:56
  • 2
    You changed the question! You can't do that. Among other things it renders answers nonsensical. Commented Oct 18, 2019 at 2:22

5 Answers 5

3

This is an answer to the OP's original question. I have no interest in changing it to attempt to answer a moving target.

Code

def doit(rides)
  { rides: rides.slice_before { |k,_| k.to_s.match? /\Aride\d*\z/ }.
                 map { |a| hashify(a.flatten.drop(1)) }.
                 reduce(&:merge) }
end

def hashify(arr)
  f,*rest = arr
  return f if rest.empty?
  { f.to_sym=>hashify(rest) }
end

Examples

Here is an example of the use of the (recursive) helper method hashify:

hashify ["lyft", :type, "car"]
  #=> {:lyft=>{:type=>"car"}} 

We are given the hash rides:

rides = {:ride1=>"lyft", :type=>"car", :ride2=>"Scoot",
         :type2=>"scooter", :ride3=>"blade", :type3=>"helicopter"} 
doit rides
  #=> {:rides=>{:lyft=>{:type=>"car"},
  #             :Scoot=>{:type2=>"scooter"},
  #             :blade=>{:type3=>"helicopter"}}} 

Let's add some more key-value pairs to rides:

rides = {:ride1=>"lyft", :type=>"car", :color=>"blue",
         :ride2=>"Scoot", :type2=>"scooter", :make=>"Vespa", :model=>"98",
         :ride3=>"blade", :type3=>"helicopter"} 
doit rides
  #=> {:rides=>{:lyft=>{:type=>{:car=>{:color=>"blue"}}},
  #             :Scoot=>{:type2=>{:scooter=>{:make=>
  #                       {:Vespa=>{:model=>"98"}}}}},
  #             :blade=>{:type3=>"helicopter"}}} 

Explanation

The steps for the first example are as follows.

enum = rides.slice_before { |k,_| k.to_s.match? /\Aride\d*\z/ }
  #=> #<Enumerator: #<Enumerator::Generator:0x00005a49d68217f0>:each> 

We can see the elements that will be generated by this enumerator by converting it to an array.

enum.to_a
  #=> [[[:ride1, "lyft"], [:type, "car"]],
  #    [[:ride2, "Scoot"], [:type2, "scooter"]],
  #    [[:ride3, "blade"], [:type3, "helicopter"]]] 

Continuing,

a = enum.map { |a| hashify(a.flatten.drop(1)) }
  #=> [{:lyft=>{:type=>"car"}},
  #    {:Scoot=>{:type2=>"scooter"}},
  #    {:blade=>{:type3=>"helicopter"}}] 
h = a.reduce(&:merge)
  #=> {:lyft=>{:type=>"car"}, :Scoot=>{:type2=>"scooter"},
  #    :blade=>{:type3=>"helicopter"}} 
{ rides: h } 
  #=> <as above> 
Sign up to request clarification or add additional context in comments.

Comments

1

It gave you undefined method push because there is no such method for a hash.

temp_rides = {"rides": {}} 
# This create a hash with `:rides` symbol as the key {:rides=>{}}

# To push an object into a hash. Use operator[]= or #store method
temp_rides[:rides][:key1] = 'value1'
temp_rides[:rides].store(:key2, 'value2')

A working example:

require 'json'

temp_rides = {"rides": {}}
rides = {:lyft => "car", :scoot => "scooter", :blade => "helicopter"}
rides.each_pair do |k, v|
    temp_rides[:rides][k] = {:type => v}
end

puts JSON.pretty_generate(temp_rides)

Comments

1

This is actually pretty easy to do with a simple transform:

def rejig(rides)
  rides.map do |name, type|
    [ name, { type: type } ]
  end.to_h
end

Where that will rework your structure into the desired shape.

Using it is easy:

require 'json'

rides = { lyft: "car", scoot: "scooter", blade: "helicopter" }

puts JSON.dump(rejig(rides))
# => {"lyft":{"type":"car"},"scoot":{"type":"scooter"},"blade":{"type":"helicopter"}}

1 Comment

Any reason you’re creating so many needless arrays when the output is all hashes? You’ve got N+1 arrays and N hashes when you need N+2 hashes. That’s a lot of waste.
0
require 'json'
temp_rides = {"rides": {}}
rides = {:lyft => "car", :scoot => "scooter", :blade => "helicopter"}
temp_rides[:rides].merge!(rides)

to get ruby hash output

temp_rides

to get json format output

JSON.dump temp_rides

Comments

0
require 'json'

rides = {:lyft => "car", :scoot => "scooter", :blade => "helicopter"}

transformed = {
  'rides' => rides.inject({}) { |h,(k,v)| h[k] = { 'type' => v }; h }
}

JSON.dump(transformed)

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.