ctfdev
ctfdev

Reputation: 39

How do I convert a float to a string that is nested inside a hash, and then puts?

I'm new to ruby. I have successfully printed "title" using puts in this code below, thats pulling from the data of "inventory".

hash["inventory"].each do |key|
  puts key["title"]
end

However, when I try to do the same for the "price" it's not printing to STDOUT. I don't know if the problem is because it's a float, or because it's in a different array. My code is as follows:

puts "#{key["price"]}"

Any insight would be greatly appreciated.


Data

{
  "inventory": [{
    "title": "ProductOne",
    "description": "This is a description for product one",
    "brand": "ProductBrandName",
    "stock": 30,
    "full-price": "24.99",
    "purchases": [{
      "channel": "online",
      "date": "2011-12-31T23:59:59+00:00",
      "price": 15.99,
      "shipping": 0.0,
      "currency": "USD",
      "user": {
        "name": "John Brown",
        "state": "KY"
      }
    }, {
      "channel": "online",
      "date": "2012-12-31T23:59:59+00:00",
      "price": 18.99,
      "shipping": 7.50,
      "currency": "USD",
      "user": {
        "name": "Jack Black",
        "state": "NY"
      }
    }]
  }]
}

Upvotes: 0

Views: 40

Answers (3)

Cary Swoveland
Cary Swoveland

Reputation: 110725

Firstly, proper indentation (note necessarily what I've used below) will help you understand the object's structure.

h = { inventory: [
        {
          title: "ProductOne",
          description: "This is a description for product one",
          brand: "ProductBrandName",
          stock: 30,
          "full-price": "24.99",
          purchases: [
            {
              channel: "online",
              date: "2011-12-31T23:59:59+00:00",
              price: 15.99,
              shipping: 0.0,
              currency: "USD",
              user: { name: "John Brown", state: "KY" }
            },
            {
              channel: "online",
              date: "2012-12-31T23:59:59+00:00",
              price: 18.99,
              shipping: 7.50,
              currency: "USD",
              user: { name: "Jack Black", state: "NY" }
            }
          ]
        }
      ]
    }

We can print the prices as follows:

h[:inventory].first[:purchases].each { |g| puts g[:price] }
15.99
18.99

Let's go through the calculations.

a = h[:inventory]
  #=> [
  #     { :title=>"ProductOne", :description=>"This is a description for product one",
  #       :brand=>"ProductBrandName", :stock=>30, :"full-price"=>"24.99",
  #       :purchases=>[{ :channel=>"online", :date=>"2011-12-31T23:59:59+00:00", 
  #                      :price=>15.99, :shipping=>0.0, :currency=>"USD",
  #                      :user=>{:name=>"John Brown", :state=>"KY"}
  #                    },
  #                    { :channel=>"online", :date=>"2012-12-31T23:59:59+00:00",
  #                      :price=>18.99, :shipping=>7.5, :currency=>"USD",
  #                      :user=>{:name=>"Jack Black", :state=>"NY"}
  #                    }
  #                   ]
  #     }
  #   ]

As you see, a is an array containing one element, a hash. To obtain that hash we select the first element of a.

b = a.first
  #=> { :title=>"ProductOne", :description=>"This is a description for product one",
  #     :brand=>"ProductBrandName", :stock=>30, :"full-price"=>"24.99",
  #     :purchases=>[{ :channel=>"online", :date=>"2011-12-31T23:59:59+00:00", 
  #                    :price=>15.99, :shipping=>0.0, :currency=>"USD",
  #                    :user=>{:name=>"John Brown", :state=>"KY"}
  #                  },
  #                  { :channel=>"online", :date=>"2012-12-31T23:59:59+00:00",
  #                    :price=>18.99, :shipping=>7.5, :currency=>"USD",
  #                    :user=>{:name=>"Jack Black", :state=>"NY"}
  #                  }
  #                 ]
  #   }

Next we want the value of the key :purchases in the hash b.

c = b[:purchases]
  #=> [
  #    { :channel=>"online", :date=>"2011-12-31T23:59:59+00:00",
  #      :price=>15.99, :shipping=>0.0, :currency=>"USD",
  #      :user=>{ :name=>"John Brown", :state=>"KY" }
  #    },
  #    { :channel=>"online", :date=>"2012-12-31T23:59:59+00:00",
  #      :price=>18.99, :shipping=>7.5, :currency=>"USD",
  #      :user=>{:name=>"Jack Black", :state=>"NY" }
  #    }
  #   ]

Since each of the three elements of c is a hash with key :price, we can print the values of that keys by looping through the hashes:

c.each { |g| puts g[:price] }
15.99
18.99

Note that:

{ "a": 1 }
  #=> {:a=>1} 
{ a: 1 }
  #=> {:a=>1}

This shows you that the double quotes are unnecessary, but that's only when the symbol comprises a single word. Consider this:

{ full price: "24.99" }
  #=>SyntaxError:...
{ full-price: "24.99" }
  #=>SyntaxError:...

Here we need the quotes:

{ "full price": "24.99" }
  #=> {:"full price"=>"24.99"} 
{ "full-price": "24.99" }
  #=> {:"full-price"=>"24.99"} 

Upvotes: 4

SoAwesomeMan
SoAwesomeMan

Reputation: 3406

DATA

require 'json'

hash = JSON.parse <<EOS
{
  "inventory": [{
    "title": "ProductOne",
    "description": "This is a description for product one",
    "brand": "ProductBrandName",
    "stock": 30,
    "full-price": "24.99",
    "purchases": [{
      "channel": "online",
      "date": "2011-12-31T23:59:59+00:00",
      "price": 15.99,
      "shipping": 0.0,
      "currency": "USD",
      "user": {
        "name": "John Brown",
        "state": "KY"
      }
    }, {
      "channel": "online",
      "date": "2012-12-31T23:59:59+00:00",
      "price": 18.99,
      "shipping": 7.50,
      "currency": "USD",
      "user": {
        "name": "Jack Black",
        "state": "NY"
      }
    }]
  }]
}
EOS

ANSWER

Here are two ways to access price:

1) Use exact hash address to access nested value:

hash['inventory'].each do |k|
  puts k['title']
  puts k['purchases'][0]['price']
  puts k['purchases'][1]['price']
end

# ProductOne
# 15.99
# 18.99

2) Loop through child nodes:

hash['inventory'].each do |k|
  puts k['title']

  k['purchases'].each do |x| 
    puts x['price']
  end
end

# ProductOne
# 15.99
# 18.99

Upvotes: 0

delta
delta

Reputation: 3818

In ["inventory"].each do |key|, key is just a normal string, not the inventory you expected.

inventory seems like json, first you need to use JSON.parse(a string)/JSON.load(or file) to convert it to json object in ruby, then you can use each to traverse the object.

Upvotes: 0

Related Questions