Lesson 10 of 10
Reports with Enumerable
- 14 min
- 6 checks
- 3 hints
- Go to task
Goal
Group, count and sort
Explanation
Reports always ask the same questions. What's the total? How many times does each value appear? What's each category's share? Who's on top? Enumerable answers them with methods you can chain one after another: sum adds up what the block returns, tally counts how many times each value appears and puts the result in a hash, group_by splits the items into groups by what the block returns, and sort_by sorts by the value you pick. Make that value negative and the order is reversed.
each_with_object(Hash.new(0)) builds the result as it goes through the items. It gives the block each item along with a single accumulator to collect the result in, then returns the accumulator at the end. Hash.new(0) is a hash whose default value is zero, which is why acc[city] += total works the very first time a city shows up.
Watch the order of the two parameters: each_with_object passes |order, acc|, the item first and then the accumulator. reduce does the opposite and passes |acc, order|. If you swap them, each order is treated as the accumulator and you get a puzzling error about nil.
Your task
From orders, work out revenue, the total of all orders, with sum; counts, the number of orders per city, with tally; by_city, the orders grouped by city, with group_by; city_totals, the revenue per city, with each_with_object; and ranking, pairs of cities and their revenue sorted from highest to lowest, with sort_by. Then print one line per city with its name and revenue, in ranking order.
Checks
6 checks- revenue is the total of all orders
- counts has the number of orders per city
- by_city groups the full orders by city
- city_totals has each city's revenue, built with each_with_object
- ranking is sorted from the highest revenue to the lowest
- One line per city was printed, in ranking order