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>
C# 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
public List<string> TopSellers(List<Sale> sales, int howMany) {
}
Worked examples
| Call | Result |
|---|---|
TopSellers(new List<Sale> { new Sale("mug", 5), new Sale("pen", 3), new Sale("mug", 2) }, 2) | new List<string> { "mug", "pen" } |
TopSellers(new List<Sale> { new Sale("zip", 1), new Sale("ace", 1) }, 2) | new List<string> { "ace", "zip" } |
TopSellers(new List<Sale> { new Sale("mug", 5), new Sale("pen", 9) }, 1) | new List<string> { "pen" } |
TopSellers(new List<Sale> { new Sale("mug", 5) }, 0) | new List<string> { } |
Hint
Aggregate into a map, then sort the entries. The tie-break is what most solutions forget.
Reference solution in C#
public List<string> TopSellers(List<Sale> sales, int howMany) {
var totals = new Dictionary<string, int>();
foreach (var s in sales) totals[s.Name] = totals.ContainsKey(s.Name) ? totals[s.Name] + s.Qty : s.Qty;
var names = totals.Keys.ToList();
names.Sort((a, b) => {
int d = totals[b] - totals[a];
return d != 0 ? d : string.CompareOrdinal(a, b);
});
if (howMany <= 0) return new List<string>();
return names.Take(howMany).ToList();
}