How to turn Python list to consecutive tuples including edge items?

Question:

For a Python list:

l = list('ABCDEFG')

How can it be turned into a list of consecutive N-tuples, with the edge cases not thrown out? Here is an example for N=3:

A
A B
A B C
B C D
C D E
D E F
E F G
F G
G

I can get close with

for first, second, third in zip(l,l[1:],l[2:]):
    print(first, second, third)

But this does not include the edge cases and can not be extended easily to other N. I can patch it up with a C-looking for loop, checking for array bound validity, but it quickly grows to be a web of nested if statements and I’m looking for a more Pythonic solution.

Asked By: user1717828

||

Answers:

You could use 3 list comprehensions to generate the edge cases and N-tuples, then just concatenate the lists:

>>> def f(l, n):
...       return ([l[:i] for i in range(1, n)] +
...               [l[i:i+n] for i in range(len(l) - n + 1)] +
...               [l[-i:] for i in range(n-1, 0, -1)])
...
>>> f(list('ABCDEFG'), 3)
[['A'], ['A', 'B'], ['A', 'B', 'C'], ['B', 'C', 'D'], ['C', 'D', 'E'], ['D', 'E', 'F'], ['E', 'F', 'G'], ['F', 'G'], ['G']]
Answered By: Eugene Yarmash

You can write a generator function that first yields items from the string in steps then yields from a itertools.zip_longest object:

from itertools import zip_longest

def func(s, N=3):
   lst = ['']*N
   for i in range(N-1):
      lst[i] = s[i]
      yield tuple(lst)
   yield from zip_longest(*map(lambda x: l[x:], range(N)), fillvalue='')

for i in func('ABCDEFG', 5):
    print(*i)

A    
A B   
A B C  
A B C D 
A B C D E
B C D E F
C D E F G
D E F G 
E F G  
F G   
G 
Answered By: Moses Koledoye

Using a simple list comprehension:

def f(seq, n):
    return [seq[max(i, 0):i + n] for i in range(-n + 1, len(seq))]

This creates a sliding window of size n over the given sequence seq, but starts n - 1 before the beginning of the sequence. The purpose of max(i, 0) is to disallow negative indexes, so that every slice is non-empty.

Example output:

>>> f('ABCDEFG', 2)
['A', 'AB', 'BC', 'CD', 'DE', 'EF', 'FG', 'G']
>>> f('ABCDEFG', 3)
['A', 'AB', 'ABC', 'BCD', 'CDE', 'DEF', 'EFG', 'FG', 'G']
Answered By: vaultah

You can try this:

l = list('ABCDEFG')
n = 3

def edge_cases(l, n):
    first = [l[:i+1] for i in range(n-1)]
    second = [l[i:i+n-1] for i in range(len(l)-n)]
    third = [l[i-n+1:] for i in range(n-1)]
    yield from first+second+third

print(list(edge_cases(l, n)))
Answered By: Ajax1234

I asked ChatGPT, and this answer works for me

import numpy as np

# create a NumPy array
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

# specify the size of each tuple
n = 3

# use a list comprehension with slicing to create consecutive tuples
tuples = [tuple(arr[i:i+n]) for i in range(len(arr)-n+1)]

# print the resulting tuples
for t in tuples:
    print(t)
Answered By: user88484
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.