Take every nth block from the list

Given a list:

import string
a = list(string.ascii_lowercase)

What is the Pythonic way to return every nth block of m elements? Note that this is different from simply returning every nth element .

The desired result of taking every 1 of 3 blocks of 3 elements (take 3, skip 6, take 3, skip 6 ...):

['a', 'b', 'c', 'j', 'k', 'l', 's', 't', 'u']

I can understand:

import itertools
s1 = a[::9]
s2 = a[1::9]
s3 = a[2::9]    
res = list(itertools.chain.from_iterable(zip(s1,s2, s3)))

Is there a cleaner way?

+6
source share
6 answers

For a fixed order of select and skip, you can wrap indexes that take modulo the total length of the window (here and here) and select only those that are below a given threshold, 3:

lst = [x for i, x in enumerate(a) if i % 9 < 3]
print(lst)
# ['a', 'b', 'c', 'j', 'k', 'l', 's', 't', 'u']

, :

def select_skip(iterable, select, skip):
    return [x for i, x in enumerate(iterable) if i % (select+skip) < select]  

print(select_skip(a, select=3, skip=6))
# ['a', 'b', 'c', 'j', 'k', 'l', 's', 't', 'u']
+2

, -

def thinger(iterable, take=3, skip=6):
    it = iter(iterable)
    try:
        while True:
            for i in range(take):
                yield next(it)
            for i in range(skip):
                next(it)
    except StopIteration:
        return

, slicable (, , ).

+2

more_itertools - , itertools recipes , more_itertools.windowed.

>  pip install more_itertools

import string

from more_itertools import windowed, flatten


m, n = 3, 6
list(flatten(windowed(string.ascii_lowercase, m, step=m+n)))
# ['a', 'b', 'c', 'j', 'k', 'l', 's', 't', 'u']

windowed, , . , (m), .

+2

, :

windows = chunks(original_iter, n=3)

Now that you are digitizing the data, how do you think about it, use islice the second option for your "step" capabilities

# flattens the list as well using chain
result = chain.from_iterable(islice(windows, 0, None, 2))
0
source

You can use list comprehension and create a function that does this for any skip, receive, and list values:

import string
import itertools
a = list(string.ascii_lowercase)
def everyNthBlock(a, take, skip):
  res = [a[i:i + take] for i in range(0, len(a) ,skip + take)]
  return list(itertools.chain(*res))

print(everyNthBlock(a, 3, 6))
#^^^^ => ['a', 'b', 'c', 'j', 'k', 'l', 's', 't', 'u']
print(everyNthBlock(a, 4, 7))
#^^^^ => ['a', 'b', 'c', 'd', 'l', 'm', 'n', 'o', 'w', 'x', 'y', 'z']
0
source

Using an incomprehensible list comprehension: D

m, n = 3, 3
[elem for blockstart in range(0, len(a), m*n) for elem in a[blockstart:blockstart+n]]    
#> ['a', 'b', 'c', 'j', 'k', 'l', 's', 't', 'u']
0
source

All Articles