Count Items Matching a Rule: Linear Scan Pattern
Count Items Matching a Rule is LeetCode 1773. You are given an array items where each element is a list [type_i, color_i, name_i], along with two strings ruleKey and ruleValue. Return the number of items that match the given rule. An item matches if the value at the attribute specified by ruleKey equals ruleValue.
Example: items = [["phone","blue","pixel"],["computer","silver","lenovo"],["phone","gold","iphone"]], ruleKey = "color", ruleValue = "silver" returns 1. Only the second item has color "silver".
Why this problem matters
Count Items Matching a Rule is about as simple as array problems get, but it introduces a pattern you will use constantly: mapping a string key to an index, then scanning an array and counting elements that satisfy a condition. This "translate, then filter" structure appears in database queries, configuration lookups, and any situation where you select records by attribute.
It also gives you practice thinking about data layout. Each item is a list of three strings, and the ruleKey tells you which position to look at. Turning a human-readable key like "color" into a numeric index like 1 is a small but important step that many beginners overlook. Getting comfortable with this mapping prepares you for problems where attribute selection is more complex.
The key insight
The first thing to do is convert ruleKey into a column index. "type" maps to 0, "color" maps to 1, and "name" maps to 2. Once you have that index, the problem reduces to a single pass through the array, comparing items[i][index] against ruleValue and counting matches.
There is no need for hashmaps, sorting, or any auxiliary data structure. You just need one integer for the index and one integer for the count. The entire solution is a mapping step followed by a counting loop.
The solution
def count_matches(items, rule_key, rule_value):
index = {"type": 0, "color": 1, "name": 2}[rule_key]
count = 0
for item in items:
if item[index] == rule_value:
count += 1
return count
The dictionary lookup {"type": 0, "color": 1, "name": 2}[rule_key] translates the string key into a positional index in one line. After that, the loop walks through every item and checks whether the value at that index matches rule_value. If it does, you increment the counter.
You could also write this with Python's built-in sum and a generator expression: return sum(1 for item in items if item[index] == rule_value). Both approaches do the same work. The explicit loop is easier to read and debug, especially in an interview where clarity matters more than brevity.
When an interviewer gives you a string that maps to an index or attribute, always translate it into a numeric index before entering your main loop. This keeps the loop body clean and avoids repeated string comparisons against the key itself.
Visual walkthrough
Here is the scan of four items with ruleKey = "color" and ruleValue = "silver". Watch how the algorithm checks only the color column (index 1) of each row and counts the matches.
Step 1: Map ruleKey to an index. "color" maps to index 1.
Before scanning, translate ruleKey into the column index: "type" = 0, "color" = 1, "name" = 2. Here we get index 1.
Step 2: Check item 0. color = "blue" does not equal "silver". No match.
Look at items[0][1] = "blue". It does not match ruleValue "silver", so count stays at 0.
Step 3: Check item 1. color = "silver" equals "silver". Match! count = 1.
items[1][1] = "silver" matches ruleValue. Increment count to 1.
Step 4: Check item 2. color = "gold" does not match. Check item 3. color = "silver" matches. count = 2.
Item 2 has "gold", no match. Item 3 has "silver", match. Final count is 2.
The key observation is that the loop body never changes based on which attribute you are filtering. The index variable absorbs all the complexity of "which column." The loop just compares item[index] against the target value every time.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Linear scan | O(n) | O(1) |
Time: O(n) where n is the number of items. You visit each item exactly once and do a constant-time string comparison.
Space: O(1). You only store the index and the count. The dictionary used for the key mapping has exactly three entries and does not grow with input size.
The building blocks
1. Key-to-index mapping
Translating a string key into a positional index is a small utility pattern, but it comes up frequently. Anytime you have structured data stored in a list or tuple and a string that describes which field to access, you need this mapping step. In Python, a dictionary literal is the cleanest way to do it. In other languages, you might use a switch statement or a simple if/else chain.
2. Predicate counting with a linear scan
The core loop is a "count items matching a predicate" scan. You initialize a counter, walk through the collection, test each element against a condition, and bump the counter on a match. This is the same structure behind Python's sum(1 for x in xs if condition(x)) idiom, SQL's COUNT(*) WHERE ..., and array .filter().length in JavaScript. Recognizing it as a reusable building block means you can apply it instantly whenever a problem asks "how many elements satisfy X?"
Edge cases
- No matches. Every item has a different value for the target attribute. The count stays at 0.
- All items match. Every item has the same value for the target attribute. The count equals the length of items.
- Single item. Only one item in the array. You either return 0 or 1.
- Different ruleKeys. The logic works identically regardless of whether ruleKey is
"type","color", or"name". The only thing that changes is the index used. - Duplicate items. Two items can be identical across all three fields. Each is counted separately, so duplicates do not collapse.
From understanding to recall
This problem feels almost too simple when you read the solution. Map the key, loop, compare, count. But simplicity is deceptive. In a timed setting, small details trip you up: did you map "color" to 1 or 2? Did you compare item[index] or item[rule_key]? Did you remember to initialize the count before the loop?
The best way to make these details automatic is to practice writing the solution from scratch. Do it today, then again in a few days. After two or three repetitions, the mapping dictionary and the counting loop become muscle memory. You will not need to think about whether "name" is index 2. You will just know.
Related posts
- Contains Duplicate - Another single-pass array scan, this time checking for repeated values using a set
- Two Sum - Builds on single-pass scanning by adding a hashmap to track complements as you go
- Find All Numbers Disappeared in an Array - A clever array scan that uses index marking instead of extra space
CodeBricks helps you move from understanding a solution to actually retaining it. Each problem is broken into reusable building blocks, and spaced repetition schedules reviews so you practice recalling them at the right intervals. Instead of re-reading solutions you have already forgotten, you actively reconstruct them, which is what builds lasting recall.