-2

I am trying to make an overlap function in python that takes any iterable, an int n, and an int m (whose default value is 1) as parameters, and produce lists of n values:

  1. The first list contains the first n values;
  2. Every subsequent list drops the first m from the previous list
  3. Adds next m values from the iterator, until there are fewer than n values to put in the returned list.

Example:

for i in overlap('abcdefghijk',4,2):
    print(i,end=' ')

Its output is ['a','b','c','d'], ['c','d','e','f'], ['e','f','g','h'], and ['g','h',i','j'] for n=4 and m=2. In this case if the function is something like this:

def overlap(iterable, n, m=1)

How can this be done? The main problem I am facing is how to stop when there are less than n values.

Current code: credits to anmol_uppal's solution.

def hide(iterable):
    for v in iterable:
        yield v

def overlap(word, n, m):
    start = 0
    while(start+n < len(word)):
        yield list(word[start:start+n])
        start += m

if __name__ == '__main__':   
    for i in overlap('abcdefghijk',3,2): 
        print(i, end=' ')
    print()
    for i in overlap(hide('abcdefghijk'),3,2): 
        print(i, end=' ')
    print()

But the problem is we cannot use len() with generators.

I have tried this code but I don't know why it's giving unexpected results for the second test case

def hide(iterable):
    for v in iterable:
        yield v

def window(seq, size, step=1):
    iters = [iter(seq) for i in range(size)]
    [next(iters[i]) for j in range(size) for i in range(-1, -j-1, -1)]
    while(True):
        yield [next(i) for i in iters]
        [next(i) for i in iters for j in range(step-1)]

if __name__ == '__main__':
    for i in window('abcdefghijk', 3, 2): 
        print(i, end=' ')
    print()
    for i in window(hide('abcdefghijk'), 3, 2): 
        print(i, end=' ')
    print()
Community
  • 1
  • 1
Hacker688
  • 93
  • 8

1 Answers1

1
def overlap(word, n,m):
    ans = []
    start = 0
    while(start+n<len(word)):
        ans.append(list(word[start:start+n]))
        start+=m

    return ans


>>> print overlap("abcdefghijk", 4, 2)
>>> [['a', 'b', 'c', 'd'], ['c', 'd', 'e', 'f'], ['e', 'f', 'g', 'h'], ['g', 'h', 'i', 'j']]
>>> print overlap("abcdefghi", 4, 2)
>>> [['a', 'b', 'c', 'd'], ['c', 'd', 'e', 'f'], ['e', 'f', 'g', 'h']]

Also if you would like to yield the results instead of returning them,then you can use the following simpler version:

def overlap(word, n,m):
    start = 0
    while(start+n<len(word)):
        yield list(word[start:start+n])
        start+=m

for i in overlap("abcdefghijk", 4, 2):
    print (i,end = " ")

To make it work with the hide() function you need to convert it to string first, so:

for i in overlap("".join(hide("abcdefghijk")),3, 2): 
    print i
ZdaR
  • 22,343
  • 7
  • 66
  • 87