uniq -c: Count Adjacent Duplicates
🎯 uniq -c collapses consecutive duplicate lines into one, prefixed with how many times it repeated.
The "consecutive" part is the catch: uniq only looks at neighbors, so a a b a becomes 2 a, 1 b, 1 a (two separate runs of a).
In Unix:
$ echo -e "tag1\ntag2\ntag1\ntag4\ntag2\ntag1" > tags.txt
$ sort tags.txt|uniq -c
3 tag1
2 tag2
1 tag4
And in Python:
from itertools import groupby
def uniq_c(text: str) -> list[tuple[int, str]]:
# need to sort the lines first to group them correctly
sorted_lines = sorted(text.splitlines())
# below takes the len of the values, intermediate results:
# ('tag1', ['tag1', 'tag1', 'tag1'])
# ('tag2', ['tag2', 'tag2'])
# ('tag4', ['tag4'])
return [(len(list(g)), key) for key, g in groupby(sorted_lines)]
assert uniq_c("tag1\ntag2\ntag1\ntag4\ntag2\ntag1") == [
(3, "tag1"),
(2, "tag2"),
(1, "tag4"),
]
Vec::last_mut — edit the final element in place
Walk the lines and look at what you last pushed. If the current line continues the run, bump its count; otherwise start a new run. last_mut on Vec can help you with this; it gives you a mutable reference to the final element (or None if the Vec is empty). For example:
let mut v = vec![1, 2, 3];
if let Some(last) = v.last_mut() {
*last += 10; // v is now [1, 2, 13]
}
Match guards — a condition on a pattern
A match guard is an extra if attached to a pattern; so now you can have the arm match only when both the pattern and the guard hold:
match Some(4) {
Some(x) if x % 2 == 0 => "even",
_ => "odd or empty",
}
This can be useful to answer: "does the last element equal this line?"
Not required, but it can make your solution more concise here.
Login to see the full task and start coding.
Topics
This is a premium exercise
Log in to unlock the full exercise and start coding.
Login to access this exercise