Note that there are some explanatory texts on larger screens.

plurals
  1. PO"sorted 1-d iterator" based on "2-d iterator" (Cartesian product of iterators)
    primarykey
    data
    text
    <p>I'm looking for a clean way to do this in Python:</p> <p>Let's say I have two iterators "iter1" and "iter2": perhaps a prime number generator, and itertools.count(). I know a priori that both are are infinite and monotonically increasing. Now I want to take some simple operation of two args "op" (perhaps operator.add or operator.mul), and calculate <strong>every element</strong> of the first iterator with <strong>every element</strong> of the next, using said operation, then yield them one at a time, sorted. Obviously, this is an infinite sequence itself. (As mentioned in comment by @RyanThompson: this would be called the <a href="http://en.wikipedia.org/wiki/Cartesian_product" rel="nofollow">Cartesian Product</a> of these sequences... or, more exactly, the 1d-sort of that product.) </p> <p>What is the best way to:</p> <ul> <li>wrap-up "iter1", "iter2", and "op" in an iterable that itself yields the values in monotonically increasing output.</li> </ul> <p>Allowable simplifying assumptions:</p> <ul> <li>If it helps, we can assume op(a,b) >= a and op(a,b) >= b.</li> <li>If it helps, we can assume op(a,b) > op(a,c) for all b > c.</li> </ul> <p>Also allowable:</p> <ul> <li>Also acceptable would be an iterator that yields values in "generally increasing" order... by which I mean the iterable could occasionally give me a number less than a previous one, but it would somehow make "side information" available (as via a method on the object) that would say "I'm not guarenteeing the next value I give you will be greater than the one I just gave you, but I AM SURE that all future values will at least be greater than N.".... and "N" itself is monotonically increasing.</li> </ul> <p>The only way I can think to do this is a sort of "diagonalization" process, where I keep an increasing number of partially processed iterables around, and "look ahead" for the minimum of all the possible next() values, and yield that. But this weird agglomeration of a heapq and a bunch of deques just seems outlandish, even before I start to code it.</p> <p>Please: do <em>not</em> base your answer on the fact that my examples mentioned primes or count().... I have several uses for this very concept that are NOT related to primes and count().</p> <hr> <p><strong>UPDATE:</strong> OMG! What a great discussion! And some great answers with really thorough explanations. Thanks so much. StackOverflow rocks; you guys rock.</p> <p>I'm going to delve in to each answer more thoroughly soon, and give the sample code a kick in the tires. From what I've read so far, my original suspicions are confirmed that there is no "simple Python idiom" to do this. Rather, by one way or another, I can't escape keeping all yielded values of iter1 and iter2 around indefinitely.</p> <p>FWIW: here's an official "test case" if you want to try your solutions.</p> <pre><code>import operator def powers_of_ten(): n = 0 while True: yield 10**n n += 1 def series_of_nines(): yield 1 n = 1 while True: yield int("9"*n) n += 1 op = operator.mul iter1 = powers_of_ten() iter2 = series_of_nines() # given (iter1, iter2, op), create an iterator that yields: # [1, 9, 10, 90, 99, 100, 900, 990, 999, 1000, 9000, 9900, 9990, 9999, 10000, ...] </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload