The best selling products this week
The weekly email lists the top products by units sold. Sales come in one row per transaction, so the same product appears many times.
- Add up the units per product name first.
- Order by units sold, largest first; products level on units go alphabetically.
- Return at most `howMany` names, or fewer if there are not that many products.
- Asking for zero or fewer returns nothing.
topSellers(sales: list<Sale>, howMany: int) → list<string>
Java needs a compiler and Drill does not host one yet, so this page is the reference rather than an exercise: the problem, worked examples, and the solution in full. To type it out, the same problem runs in Python.
Where you start
List<String> topSellers(List<Sale> sales, int howMany) {
}
Worked examples
| Call | Result |
|---|---|
topSellers(Main.<Sale>ls(new Sale("mug", 5), new Sale("pen", 3), new Sale("mug", 2)), 2) | Main.<String>ls("mug", "pen") |
topSellers(Main.<Sale>ls(new Sale("zip", 1), new Sale("ace", 1)), 2) | Main.<String>ls("ace", "zip") |
topSellers(Main.<Sale>ls(new Sale("mug", 5), new Sale("pen", 9)), 1) | Main.<String>ls("pen") |
topSellers(Main.<Sale>ls(new Sale("mug", 5)), 0) | Main.<String>ls() |
Hint
Aggregate into a map, then sort the entries. The tie-break is what most solutions forget.
Reference solution in Java
List<String> topSellers(List<Sale> sales, int howMany) {
Map<String, Integer> totals = new LinkedHashMap<>();
for (Sale s : sales) totals.merge(s.name, s.qty, Integer::sum);
List<String> names = new ArrayList<>(totals.keySet());
names.sort((a, b) -> {
int d = totals.get(b) - totals.get(a);
return d != 0 ? d : a.compareTo(b);
});
if (howMany <= 0) return new ArrayList<>();
return new ArrayList<>(names.subList(0, Math.min(howMany, names.size())));
}