如何实现可生成任意两个输入生成器交集的通用生成器?
Got it, let's work through this problem step by step. First, we'll tidy up your existing generators (they have a couple of small gaps) and then build that universal intersection generator you're asking for.
Fixed & Optimized Existing Generators
First, let's polish your current code. The is_prime function can be way more efficient, and the Fibonacci generator was cut off mid-implementation:
def is_prime(num): if num <= 1: return False if num == 2: return True if num % 2 == 0: return False # Only check odd divisors up to sqrt(num) (big efficiency boost) for i in range(3, int(num**0.5) + 1, 2): if num % i == 0: return False return True def primes(): yield 2 i = 3 while True: if is_prime(i): yield i i += 2 def fibonacci_numbers(): yield 1 a, b = 0, 1 while True: c = a + b yield c a, b = b, c
A quick note on the is_prime optimization: we skip even numbers after checking 2, and only test divisors up to the square root of the number—no need to check beyond that, since any factor larger than the square root would pair with a smaller one we already tested.
Universal Intersection Generator
Since both primes and Fibonacci numbers are generated in strictly increasing order, we can use a two-pointer approach to find their intersection efficiently (no need to store infinite elements in memory). Here's the generic generator that works for any two ascending infinite generators:
def generator_intersection(gen1, gen2): # Grab the first value from each generator val1 = next(gen1) val2 = next(gen2) while True: if val1 == val2: # Found a common value—yield it, then move both generators forward yield val1 val1 = next(gen1) val2 = next(gen2) elif val1 < val2: # The first generator's value is smaller—advance it to catch up val1 = next(gen1) else: # The second generator's value is smaller—advance it instead val2 = next(gen2)
How this works: We keep track of the current value from each generator. Since both sequences are sorted, we only need to advance the generator with the smaller current value. When the values match, that's our intersection element—we yield it and advance both generators.
Test It Out
Let's test this with your primes and Fibonacci generators. A quick heads-up: your original Fibonacci generator starts with 1, which isn't a prime. If you want to skip non-prime Fibonacci numbers right off the bat, adjust the Fibonacci generator to start with 2 instead:
def fibonacci_numbers(): yield 2 a, b = 1, 2 while True: c = a + b yield c a, b = b, c
Now let's fetch the first few Fibonacci primes (which are rare, but we can get the first handful):
# Initialize our generators prime_gen = primes() fib_gen = fibonacci_numbers() # Create the intersection generator common_values = generator_intersection(prime_gen, fib_gen) # Print the first 5 intersection elements for _ in range(5): print(next(common_values))
This will output:
2 3 5 13 89
This approach isn't limited to primes and Fibonacci—you can use generator_intersection with any two strictly increasing infinite generators as long as they produce comparable values.
内容的提问来源于stack exchange,提问作者user9199674

