Drill

ProblemsGo › reporting

The best selling products this week

mediumreportingHash mapsSortingArraysGo

The weekly email lists the top products by units sold. Sales come in one row per transaction, so the same product appears many times.

topSellers(sales: list<Sale>, howMany: int) → list<string>

Go 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.

Solve it in Python →

Where you start

func topSellers(sales []Sale, howMany int) []string {
	
}

Worked examples

CallResult
topSellers([]Sale{Sale{Name: "mug", Qty: 5}, Sale{Name: "pen", Qty: 3}, Sale{Name: "mug", Qty: 2}}, 2)[]string{"mug", "pen"}
topSellers([]Sale{Sale{Name: "zip", Qty: 1}, Sale{Name: "ace", Qty: 1}}, 2)[]string{"ace", "zip"}
topSellers([]Sale{Sale{Name: "mug", Qty: 5}, Sale{Name: "pen", Qty: 9}}, 1)[]string{"pen"}
topSellers([]Sale{Sale{Name: "mug", Qty: 5}}, 0)[]string{}

Hint

Aggregate into a map, then sort the entries. The tie-break is what most solutions forget.

Reference solution in Go
func topSellers(sales []Sale, howMany int) []string {
	totals := map[string]int{}
	names := []string{}
	for _, s := range sales {
		if _, ok := totals[s.Name]; !ok {
			names = append(names, s.Name)
		}
		totals[s.Name] += s.Qty
	}
	sort.Slice(names, func(i, j int) bool {
		if totals[names[i]] != totals[names[j]] {
			return totals[names[i]] > totals[names[j]]
		}
		return names[i] < names[j]
	})
	if howMany <= 0 {
		return []string{}
	}
	if howMany < len(names) {
		names = names[:howMany]
	}
	return names
}

The same problem in another language

More reporting problems in Go