{ }codelper

Learn › Python

Going further · 24

Counting, running totals, grouping

In one pass: count what matches, carry the value so far, and collect items by key.

Counting, running values and grouping are three basic ways to build an answer while walking through data once.
The example below looks at scores one by one, printing the total and the best score so far, counts how many are 80 or more, and groups the scores by tens (the 60s, the 70s, …).

scores = list(map(int, input().split()))count = 0          # 80점 이상인 점수의 개수total = 0          # 지금까지의 합best = scores[0]   # 지금까지의 최고 점수groups = {}        # 십의 자리(60, 70, …) → 그 묶음의 점수들for s in scores:    if s >= 80:        count += 1    total += s    if s > best:        best = s    print(total, best)    key = s // 10 * 10    if key not in groups:        groups[key] = []      # 처음 보는 열쇠면 빈 목록부터    groups[key].append(s)print(count)for key in sorted(groups):    print(f"{key}:", *groups[key])
stdin
72 85 90 68 85 77 93
stdout
72 72
157 85
247 90
315 90
400 90
477 90
570 93
4
60: 68
70: 72 77
80: 85 85
90: 90 93

Key points

  • A count starts at 0 and goes up by 1 only when the condition holds.
    Unlike a sum, you add 1, not the value.
  • A running value is a variable you update for every item.
    The total so far (total) and the best so far (best) always hold "the answer up to here", so you can print a result in the middle.
    The total += i from the loops lesson is exactly this shape.
  • Create running variables before the loop.
    Counts and sums start at 0; a best or worst starts at the first value.
  • Grouping picks a key for each value (in the example 68 → 60, 72 → 70) and adds the value to that key's list in a dictionary.
    A counting dictionary (the dictionaries lesson) holds numbers; a grouping dictionary holds lists.
  • A key you see for the first time has no list yet.
    Put an empty list in first, then add the value.
  • You do not need three separate loops.
    The example counts, keeps running values and groups in a single loop.

How each language writes it

PythonCount with count += 1 (in one line: sum(1 for s in scores if s >= 80)), running value with total += s.
Group as in the example: if key not in groups: groups[key] = [], then groups[key].append(s); shorter: groups.setdefault(key, []).append(s) or collections.defaultdict(list)
JavaScriptCount with count++ (in one line: scores.filter((s) => s >= 80).length), running value with total += s.
Group in a Map: if (!groups.has(key)) groups.set(key, []);, then groups.get(key).push(s)
TypeScriptSame as JavaScript, with types as in new Map<number, number[]>().
groups.get(key) may be undefined by its type, so calling .push on it directly is a type error (TS2532).
Store the result in a variable and check for undefined, as the example does
JavaCount with count++ (in one line: scores.stream().filter(s -> s >= 80).count()), running value with total += s.
Group in a Map<Integer, List<Integer>>: check with containsKey and put(key, new ArrayList<>()); shorter: groups.computeIfAbsent(key, k -> new ArrayList<>()).add(s).
A TreeMap iterates in key order
C#Count with count++ (with LINQ: scores.Count(s => s >= 80)), running value with total += s.
Group in a Dictionary<int, List<int>>: if (!groups.ContainsKey(key)) groups[key] = new List<int>();, then groups[key].Add(s).
A SortedDictionary iterates in key order
C++Count with count++ (there is also std::count_if in <algorithm>), running value with total += s.
Grouping is one line with std::map<int, std::vector<int>>: groups[key].push_back(s).
For a missing key, [] creates an empty vector for you
CCounting and running values are the same as elsewhere (count++, total += s).
There is no dictionary, so grouping is done by hand.
When the key is a small integer, use a 2D array as the example does, groups[key][sizes[key]++] = s, and keep each group's size in sizes
CraykonCount with count++, running value with total += s.
Group in a Dict(): if (!groups.Contains(key)) { groups[key] = []; }, then groups[key].Add(s).
To print in key order, Sort() the list from groups.Keys and loop over it

Common mistakes

Writing =+ instead of +=

int count = 0;
int scores[] = {72, 85, 90};
for (int i = 0; i < 3; i++)
    if (scores[i] >= 80) count =+ 1;
printf("%d\n", count);

→ 1 — it runs without an error, but the answer is not 2. count =+ 1 means count = +1: "store 1"

Write count += 1.
If a count always comes out as 1, check the order of these two characters first.

Setting the running variable to 0 inside the loop

const scores = [72, 85, 90];
for (const s of scores) {
  let total = 0;
  total += s;
  console.log(total);
}

→ 72, 85, 90 — it goes back to 0 every lap, so nothing accumulates

Give total its starting value (0) once, before the loop, and only add to it inside.
Python and Craykon have no declaring word like let or int, but with total = 0 inside the loop they print the same 72, 85, 90.

Adding to a group without making its list firstJava

Map<Integer, List<Integer>> groups = new TreeMap<>();
int s = 68;
int key = s / 10 * 10;
groups.get(key).add(s);

→ NullPointerException — the key is missing, so get returned null

First do if (!groups.containsKey(key)) groups.put(key, new ArrayList<>());, or write groups.computeIfAbsent(key, k -> new ArrayList<>()).add(s).

How languages differ
Each group needs its own list.
In Python, preparing the keys with groups = dict.fromkeys([60, 70], []) makes every key share one single list, so adding 68 and 72 to different keys gives {60: [68, 72], 70: [68, 72]}.
Make a new [] for each key the first time you see it, as the example does.

Practice