Go Map Range Iterator
This challenge asks you to implement a mechanism to iterate over a Go map using a range-like syntax, similar to how you would iterate over slices or arrays. This is a common pattern that can make map traversal more idiomatic and readable in certain situations, especially when you want to selectively process map elements based on a condition.
Problem Description
Your task is to create a function in Go that takes a map and a filter function as input. The function should return an iterator that yields values from the map that satisfy the filter condition. The iterator should behave like Go's built-in range keyword, allowing you to iterate through the filtered elements.
Specifically, you need to:
- Define an iterator type: This type will encapsulate the map, the filter function, and the internal state for iteration.
- Implement a
Nextmethod: This method will advance the iterator to the next valid element that meets the filter criteria. It should returntrueif a valid element was found andfalseotherwise. - Implement a
Valuemethod: This method should return the value of the current element being pointed to by the iterator. - Implement a
Keymethod (optional but recommended): This method should return the key of the current element. - Provide a function to create the iterator: This function will take the map and the filter function as arguments and return an instance of your iterator type.
Key Requirements:
- The iterator should only yield elements for which the provided filter function returns
true. - The order of iteration over map elements is not guaranteed, as maps in Go are inherently unordered.
- The filter function should accept a key and a value from the map and return a boolean.
Expected Behavior:
When iterating using the returned iterator, you should be able to access the Key and Value of the elements that pass the filter. The iteration should stop gracefully when Next() returns false.
Edge Cases:
- Empty Map: The iterator should handle an empty input map correctly, with
Next()immediately returningfalse. - No Elements Satisfy Filter: If no elements in the map satisfy the filter condition,
Next()should returnfalseafter the initial call. - Filter Function Panics: While not strictly a requirement to handle panics, be aware that the filter function could potentially panic.
Examples
Example 1:
Let's say we have a map of student scores and we want to find students who scored above 80.
// Input Map
scores := map[string]int{
"Alice": 85,
"Bob": 70,
"Charlie": 92,
"David": 78,
}
// Filter function: returns true if score > 80
filter := func(key string, value int) bool {
return value > 80
}
// Assume `NewMapIterator` is your function to create the iterator
iterator := NewMapIterator(scores, filter)
// Iterating and collecting results
var highScorers []string
for iterator.Next() {
highScorers = append(highScorers, iterator.Key())
}
// Expected Output: ["Alice", "Charlie"] or ["Charlie", "Alice"] (order may vary)
Example 2:
Iterating over a map of integers and filtering for even numbers.
// Input Map
numbers := map[int]int{
1: 2,
2: 3,
3: 4,
4: 5,
5: 6,
}
// Filter function: returns true if the value is even
filter := func(key int, value int) bool {
return value%2 == 0
}
// Assume `NewMapIterator` is your function to create the iterator
iterator := NewMapIterator(numbers, filter)
// Iterating and collecting results
var evenValues []int
for iterator.Next() {
evenValues = append(evenValues, iterator.Value())
}
// Expected Output: [2, 4, 6] (order may vary)
Example 3: Empty Map
// Input Map
emptyMap := map[string]int{}
// Filter function (can be anything, won't be called if map is empty)
filter := func(key string, value int) bool {
return true
}
// Assume `NewMapIterator` is your function to create the iterator
iterator := NewMapIterator(emptyMap, filter)
// Iterating
hasNext := iterator.Next() // Should be false
// Expected Output: hasNext is false
Constraints
- The map can contain up to 1,000,000 elements.
- Keys and values can be of any type supported by Go maps (
comparablefor keys,anyfor values). - The solution should be efficient, aiming for O(N) time complexity in the worst case for iterating through all elements once.
- The filter function should ideally have a constant time complexity for each element it processes.
Notes
Consider how you will manage the iteration state within your iterator type. You'll need to keep track of which elements have already been processed or which are still available. Remember that Go maps do not guarantee iteration order, so your solution should reflect this. You might want to explore using a temporary slice to store keys to ensure predictable iteration within your iterator if that simplifies your implementation, but the fundamental output order will still depend on the map's internal structure.