Select neighboring pairs (or triads, etc.) from the list

I can do this using list indexes ...

lst =[1,2,3,4,5,6] [ [lst[i] , lst[i+1]] for i in range( len(lst) - 1 )] 

or

 lst =[1,2,3,4,5,6] for i in range(len(lst)-1): entities.append([lst[i],lst[i+1]]) 

But is there a smarter way? Maybe using iterators? What about performance?

+4
source share
5 answers

You got some clever answers here, but I would suggest that the most obvious way to do this is simply using the built-in indexing of slices. For instance:

 def gen_k_slices(seq, k): for i in range(len(seq) - k + 1): yield seq[i:i+k] 

Here is a small test driver:

 TEST = [1, 2, 3, 4, 5, 6] for k in range(8): print("k={} -> {}".format(k, list(gen_k_slices(TEST, k)))) 

and its conclusion:

 k=0 -> [[], [], [], [], [], [], []] k=1 -> [[1], [2], [3], [4], [5], [6]] k=2 -> [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]] k=3 -> [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]] k=4 -> [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]] k=5 -> [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6]] k=6 -> [[1, 2, 3, 4, 5, 6]] k=7 -> [] 

I also don't like the result for k = 0 :-)

+4
source

For a general solution (since you asked for pairs, triples, etc.), use itertools.tee :

 from itertools import tee def adjacent_tuples(iterable, n=2): iterators = tee(iterable, n) for i, iterator in enumerate(iterators): for j in range(i): next(iterator) return zip(*iterators) 

This uses minimal memory and works for any tuple length:

 >>> list(adjacent_tuples(range(8), 4)) [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5), (3, 4, 5, 6), (4, 5, 6, 7)] 
+5
source

You can use zip() :

 >>> lst = [1,2,3,4,5,6] >>> list(zip(lst[:-1],lst[1:])) [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] >>> list(zip(lst[:-2],lst[1:-1],lst[2:])) [(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6)] 
+2
source

You can use zip iterators, one regular and one shifted:

 >>> it = iter(lst) >>> it.next() 1 >>> zip(iter(lst), it) [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] 

Here's the corresponding generator (using izip ):

 from itertools import izip def my_zip(l): i1 = iter(l) i2 = iter(l) i2.next() for value in izip(i1, i2): yield value lst = [1,2,3,4,5,6] print list(my_zip(lst)) # prints [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] 
+1
source

The iterator will be like that.

 def iterate_couples(lst): for i in range(len(lst) - 1): yield [lst[i], lst[i + 1]] 
+1
source

Source: https://habr.com/ru/post/1502314/


All Articles