Inventory Snapshot
Part of the Logic & Flow section of Coddy's Ruby journey — lesson 55 of 56.
An inventory report that exercises hashes, Enumerable chains, group_by, and a touch of formatting.
Challenge
MediumThe array inventory is given. Each item is a hash with :name, :category, :qty, and :price.
Print four lines:
- Total inventory value across all items (
qty * price, summed), printed as an integer. - The category with the highest item count, in the format
Top category: <name> (<count>). Ties broken alphabetically by category name. - Names of items out of stock (
qty == 0), sorted alphabetically, joined with,. If none, print(none). - Names of the top 3 most expensive items by unit price, highest first, joined with
,. Ties broken by name alphabetically.
For the default inventory the output is:
232
Top category: food (3)
milk
chair, lamp, milkCheat sheet
Working with arrays of hashes using Enumerable methods:
# Sum with calculation per element
inventory.sum { |item| item[:qty] * item[:price] }
# Group by a key and count
groups = inventory.group_by { |item| item[:category] }
groups.max_by { |cat, items| [items.count, ...] }
# Filter, sort, and join
inventory.select { |item| item[:qty] == 0 }
.map { |item| item[:name] }
.sort
.join(", ")
# Sort by multiple criteria (ties broken alphabetically)
inventory.sort_by { |item| [-item[:price], item[:name]] }
.first(3)
.map { |item| item[:name] }
.join(", ")
Breaking ties alphabetically when using max_by with counts:
# Higher count wins; on tie, alphabetically first (negate string for max_by)
groups.max_by { |cat, items| [items.count, -cat.ord] }
# Or use min_by on negated count + natural string order
groups.sort_by { |cat, items| [-items.count, cat] }.first
Try it yourself
inventory = [
{ name: "apple", category: "food", qty: 10, price: 2 },
{ name: "bread", category: "food", qty: 4, price: 3 },
{ name: "milk", category: "food", qty: 0, price: 4 },
{ name: "chair", category: "furniture", qty: 2, price: 35 },
{ name: "lamp", category: "furniture", qty: 5, price: 20 },
{ name: "pencil", category: "stationery", qty: 30, price: 1 }
]
# TODO: print total value, top category, out-of-stock names, top 3 by price
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Strings In Depth
String Methods OverviewString InterpolationIterating Over StringsSplit and JoinRecap - String Weaver4Blocks, Procs & Lambdas
What is a Block?do..end vs BracesThe yield KeywordBlock ParametersProcs and LambdasRecap - Custom Iterator7Hashes Part 2
Hash.new with DefaultsIterating HashesNested HashesMerging and TransformingRecap - Frequency Counter10Project - Student Records
Project OverviewAdd Student5Enumerable Powerhouse
Select and RejectChaining MapReduce / Injectcount, all?, any?, none?group_by and partitionsort_by, min_by, max_byRecap - Data Pipeline8Advanced Decision Making
Case with Classes & RegexMulti-value whenTernary OperatorInline if / unlessRecap - Grade Classifier