-2
c = [1,2,3,4,5,6,7,8,9,10]

for a,b in func(c):
    doSomething()

So func() have to return (1,2) (2,3) (3,4) ... (8,9) (9,10)

Is there a elegant method in python 2.7 to achieve this?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
quesaionasis
  • 137
  • 1
  • 2
  • 11

5 Answers5

6

Sure, there are many ways. Simplest:

def func(alist):
    return zip(alist, alist[1:])

This spends a lot of memory in Python 2, since zip makes an actual list and so does the slicing. There are several alternatives focused on generators that offer memory savings, such as a very simple:

def func(alist):
    it = iter(alist)
    old = next(it, None)
    for new in it:
        yield old, new
        old = new

Or you can get fancier deploying the powerful itertools instead, as in the pairwise recipe proposed by @HughBothwell .

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
5

The itertools documentation has a recipe for this:

from itertools import tee, izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

then

for a,b in pairwise(c):
    doSomething(a, b)
Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
  • why use python code while built-in `zip` could do that with `C`? – Mazdak Feb 01 '15 at 18:14
  • 1
    @KasraAD: two main circumstances: one, if you are working on a very long list (`zip[:1]` makes a second copy of the list to iterate over); two, if you are working from a generator (`tee` uses a deque to store each value the first time it is requested). For short lists the `zip(c, c[:1])` approach is entirely suitable. – Hugh Bothwell Feb 01 '15 at 18:27
  • yes im agree . and i just mean for this case ;) . – Mazdak Feb 01 '15 at 21:57
1

There are many ways

>>> a = [1,2,3,4,5,6,7,8,9,10]
>>> list(zip(a,a[1:]))
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10)]

The other ways are

  • [(a[i],a[i+1]) for i in range(len(a)-1)]

As you wanter a function you can do

func = lambda a : list(zip(a,a[1:]))
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
0

You can use zip:

>>> def pair(sample_list):
...    return zip(sample_list,sample_list[1:])
... 
>>> pair(a)
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10)]

Or with iter() that return an iterator , so you can use next() attribute of iterator in a list comprehension to get the proper pairs , note that in both recipes the second object need to be slice from first element to end [1:] , and i following you need to slice the main list from leading to end except the last element , because the iterator will chose it :

>>> def pair(sample_list):
...    it_a=iter(sample_list[1:])
...    return [(i,it_a.next()) for i in sample_list[:-1]]
... 
>>> pair(a)
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10)]
Mazdak
  • 105,000
  • 18
  • 159
  • 188
0

Try this:

c = list(range(1, 11))
for a, b in zip(c[:-1], c[1:]):
    doSomething()
Alfred Huang
  • 17,654
  • 32
  • 118
  • 189
  • Using `c[:-1]` is wasteful; it makes an entire copy of the last in order to exclude the last element which `zip` would have stopped before anyway. – Hugh Bothwell Feb 01 '15 at 18:26