The Tag Analyst
A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- medium
- Seniority
- L4
- Asked in
- Gemini
Problem
A platform engineer is reconciling the tags on two resources, where either list may repeat a tag but each tag only ever counts once. Split them into the tags on both tags_a and tags_b, the ones only in tags_a, and the ones only in tags_b, each group in alphabetical order.
Two sets of labels, one analysis.
Example
Input:
tags_a = ["python","sql","spark"], tags_b = ["sql","spark","airflow"]
Output:
{"both":["spark","sql"],"only_a":["python"],"only_b":["airflow"]}Worked solution and explanation
This is set algebra dressed up as tag reconciliation. Anyone can name the three buckets. What separates candidates is collapsing the repeats before partitioning, then putting each bucket back into a fixed order. Write [t for t in tags_a if t not in tags_b] and an input like ['python', 'python', 'sql'] hands back 'python' twice in the only-in-a group. Return the raw sets instead and the order shifts from run to run, so a graded, alphabetical answer stops being reproducible.
Walking it through
Step 1: Collapse each list into a set
The statement says a tag only ever counts once, so set(tags_a) and set(tags_b) are the real inputs. Deduplication happens here, once, before any comparison.
Step 2: Partition with & and -
Shared tags are set_a & set_b. Each exclusive group is a difference taken in its own direction: set_a - set_b and set_b - set_a. Those three sets cover every tag exactly once.
Step 3: Sort every group, not just one
A set has no order you can promise. sorted() turns each group into an alphabetical list, and that is the only order that is stable across runs and matches what the example shows.
def compare_tags(tags_a: list, tags_b: list) -> dict:
set_a = set(tags_a)
set_b = set(tags_b)
both = set_a & set_b
only_a = set_a - set_b
only_b = set_b - set_a
result = {
"both": sorted(both),
"only_a": sorted(only_a),
"only_b": sorted(only_b)
}
return result- Comprehension over the raw lists
[t for t in tags_a if t not in tags_b]keeps every repeat and keeps input order. It also runs O(n*m), becauseinon a list is a scan.- Sets, then sort
sorted(set_a - set_b)drops repeats, runs in linear time to build, and comes out alphabetical no matter how the inputs were ordered.
Common follow-up questions
- What if you needed to preserve each tag's first-seen order instead of sorting? (Tests filtering the original list against a set while tracking what has already been emitted.)
- How would you handle case-insensitive comparison, so 'Python' and 'python' match? (Tests normalizing before building the sets, and deciding which spelling to report.)
- What if each tag carried a weight and you needed the weighted overlap? (Tests moving from sets to dicts keyed by tag.)