1

Suppose I have a set {a, b, c, d}. I want to create a "path" from it, which is a generator that yields (a, b), then (b, c), then (c, d) (of course set is unordered, so any other path through the elements is acceptable).

What is the best way to do this?

max
  • 49,282
  • 56
  • 208
  • 355

5 Answers5

3
def gen(seq):
   it = iter(seq)
   a, b = next(it), next(it)
   while True:
     yield (a, b)
     a, b = b, next(it)

print(list(gen({1, 2, 3, 4})))
NPE
  • 486,780
  • 108
  • 951
  • 1,012
3

Here's an example using the pairwise() recipe from http://docs.python.org/3/library/itertools.html#itertools-recipes

>>> from itertools import tee
>>> def pairwise(iterable):
...     "s -> (s0,s1), (s1,s2), (s2, s3), ..."
...     a, b = tee(iterable)
...     next(b, None)
...     return zip(a, b)
...
>>> for pair in pairwise({1, 2, 3, 4}):
...     print(pair)
...
(1, 2)
(2, 3)
(3, 4)
stranac
  • 26,638
  • 5
  • 25
  • 30
2

Use the Rolling or sliding window iterator in Python solution:

>>> from itertools import islice
>>> def window(seq, n=2):
...     "Returns a sliding window (of width n) over data from the iterable"
...     "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
...     it = iter(seq)
...     result = tuple(islice(it, n))
...     if len(result) == n:
...         yield result    
...     for elem in it:
...         result = result[1:] + (elem,)
...         yield result
... 
>>> path = window({1, 2, 3, 4})
>>> for step in gen:
...     print path
(1, 2)
(2, 3)
(3, 4)

This happens to follow sorted order, because for python integers hash(x) == x and thus the sequence of 1, 2, 3, 4 is inserted in that order into the set.

Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I like this recipe, even though it's more general than I need. I wonder why this recipe was replaced with another one in the current `itertools` documentation? – max Dec 12 '12 at 08:56
  • @max: It was replaced with the [`pairwise` recipe to illustrate `tee`](http://hg.python.org/cpython/rev/ea058504104c). The recipes are there to show off the functions of the module, and `tee()` was yet to be used on that page. – Martijn Pieters Dec 12 '12 at 09:55
0

You could use the pairwise itertools recipe:

>>> from itertools import tee
>>> def pairwise(iterable):
        a, b = tee(iterable)
        next(b, None)
        return zip(a, b)

>>> pairwise({1, 2, 3, 4})
<zip object at 0x0000000003B34D88>
>>> list(_)
[(1, 2), (2, 3), (3, 4)]
poke
  • 369,085
  • 72
  • 557
  • 602
0

Now that I understand the question

from itertools import islice
a = {'A','B','C','D'}
zip(a,islice(a,1,None))
#[('A', 'C'), ('C', 'B'), ('B', 'D')]
Piti Ongmongkolkul
  • 2,110
  • 21
  • 20