Hone logo
Hone
Problems

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 Next method: This method will advance the iterator to the next valid element that meets the filter criteria. It should return true if a valid element was found and false otherwise.
  • Implement a Value method: This method should return the value of the current element being pointed to by the iterator.
  • Implement a Key method (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 returning false.
  • No Elements Satisfy Filter: If no elements in the map satisfy the filter condition, Next() should return false after 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 (comparable for keys, any for 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.

Loading editor...
go