1

I have an object:

EURO_COUNTRIES = ['France', 'Germany', 'Spain']
fruit_production = {
  cuba: {
  #meaning: country c produces k kilograms of fruit in region r for season s
    winter: [{north: 1}, {south: nil}, {east: 4}, {west: 4}],
    summer: [{north: nil}, {south: 5}, {east: ""}, {west: 5}],
  },
  spain: {
    fall: [{north: 7}, {}],
    summer: [{north: nil}, {south: "5"}, {east: 2}, {west: '5'}],
    spring: []
  }
#and the list goes on for hundreds of countries
}fruit_production = {
  cuba: {
  #meaning: country c produces k kilograms of fruit in region r for season s
    winter: [{north: 1}, {south: nil}, {east: 4}, {west: 4}],
    summer: [{north: nil}, {south: 5}, {east: ""}, {west: 5}],
  },
  spain: {
    fall: [{north: 7}, {}],
    summer: [{north: nil}, {south: "5"}, {east: 2}, {west: '5'}],
    spring: []
  }
#and the list goes on for hundreds of countries
}

I tried to convert it to JSON object with json.parse(fruit_production), but how can I can actually get the data from it and loop it after that? For example:

  1. Return the country with the highest year-round fruit yield 
  2. Return the European country with the highest warm season (spring, summer) fruit yield
  3. Return a mapping from country to total yearly yield, i.e {netherlands: 1818, thailand: 8200, etc...}
  4. Return a mapping of the total worldwide yields per region, e.g {north: 28333, south: 91339, east: 14343, west: 50290}

2 Answers 2

1

you can convert to json with to_json

>   fruit_production.to_json
=> "{\"cuba\":{\"winter\":[{\"north\":1},{\"south\":null},{\"east\":4},{\"west\":4}],\"summer\":[{\"north\":null},{\"south\":5},{\"east\":\"\"},{\"west\":5}]},\"spain\":{\"fall\":[{\"north\":7},{}],\"summer\":[{\"north\":null},{\"south\":\"5\"},{\"east\":2},{\"west\":\"5\"}],\"spring\":[]}}"

As for retrieving the info from a json string, I think you're better off just to convert it back to a hash and work with that.

1, 3) You can get the yearly yield for each country by summing over season and region and taking the max.

note: your hash of yield by region is unnecessarily complex - you have an array of single-element hashes instead of a single hash indexed by region.

current: [{:north=>nil}, {:south=>"5"}, {:east=>2}, {:west=>"5"}]

better: {:north=>nil, :south=>"5", :east=>2, :west=>"5"}

However, this will work with what you've got, though I'm sure it can be simplified, (especially if you take my recommendation on the region-production structure - you can get rid of the sometimes-confusing inject function and just sum on the values of the hash):

by_country = Hash[fruit_production.map { |country, production| [country, production.map {|season, data| data.inject(0) { |sum, v| sum + v.values.map(&:to_i).sum } }.sum]}]

=> {:cuba=>19, :spain=>19}

Uh oh, you have a tie! I don't know what you want to do with that case, but you can just select one max pretty easily:

by_country.max_by { |k,v| v }
=> [:cuba, 19]

2) You can get a subset of fruit_production for European countries by selecting the elements of fruit_production whose key (after some string manipulation) matches one of the country names in the list:

 euro_fruit_production = fruit_production.select {|k,v| EURO_COUNTRIES.include?(k.to_s.titleize)}

=> {:spain=>{:fall=>[{:north=>7}, {}], :summer=>[{:north=>nil}, {:south=>"5"}, {:east=>2}, {:west=>"5"}], :spring=>[]}}

you can use that to work out seasonal totals. Good luck with the rest!

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

Comments

1

To get you started off, it's late and I'm sure I've missed something. There are plenty of ways going about this as well.

data = fruit_production.each_with_object(Hash.new {|k,v| k[v] = Hash.new(0)}) do |(country, seasons), memo|
  seasons.each do |season, regions|
    regions.each do |region|
      fruit_yield = Integer(region.values.first) rescue 0
      memo[:total_highest_profit][country] += fruit_yield
      memo[:total_region_yield][region.keys.first] += fruit_yield if region.keys.first
      memo[:total_warm_season][country] += fruit_yield if season == :summer || season == :spring
    end
  end
end
# => {
#     :total_region_yield=>{:north=>8, :south=>10, :east=>6, :west=>14},
#     :total_highest_profit=>{:cuba=>19, :spain=>19}, 
#     :total_warm_season=>{:cuba=>10, :spain=>12}
#    }

You can get whatever you want from this data, such as highest country or European country (for this you'll have to use array#include?).

data[:total_highest_profit].max_by {|_, v| v}
# => [:cuba, 19]

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.