itertools.intersect?
Andrew Henshaw
andrew.henshaw at gtri.gatech.edu
Mon Jun 15 10:40:24 EDT 2009
"Raymond Hettinger" <python at rcn.com> wrote in message
news:fb1feeeb-c430-4ca7-9e76-fea02ea3ef6f at v23g2000pro.googlegroups.com...
> [David Wilson]
>> The problem is simple: given one or more ordered sequences, return
>> only the objects that appear in each sequence, without reading the
>> whole set into memory. This is basically an SQL many-many join.
>
> FWIW, this is equivalent to the Welfare Crook problem in David Gries
> book, The Science of Programming, http://tinyurl.com/mzoqk4 .
>
>
>> I thought it could be accomplished through recursively embedded
>> generators, but that approach failed in the end.
>
> Translated into Python, David Gries' solution looks like this:
>
> def intersect(f, g, h):
> i = j = k = 0
> try:
> while True:
> if f[i] < g[j]:
> i += 1
> elif g[j] < h[k]:
> j += 1
> elif h[k] < f[i]:
> k += 1
> else:
> print(f[i])
> i += 1
> except IndexError:
> pass
>
> streams = [sorted(sample(range(50), 30)) for i in range(3)]
> for s in streams:
> print(s)
> intersect(*streams)
>
>
> Raymond
Here's my translation of your code to support variable number of streams:
def intersect(*s):
num_streams = len(s)
indices = [0]*num_streams
try:
while True:
for i in range(num_streams):
j = (i + 1) % num_streams
if s[i][indices[i]] < s[j][indices[j]]:
indices[i] += 1
break
else:
print(s[0][indices[0]])
indices[0] += 1
except IndexError:
pass
More information about the Python-list
mailing list