zhangdi
zhangdi

Reputation: 119

function takes iterabls and return a list

def group_when(iterable,p):
    x = iter(iterable)
    z = []
    d = []
    try:
        while True:
            y = next(x)
            if p(y) == False:
                z.append(y)
            elif p(y) == True:
                z.append(y)
                d.append(z) 
                z = []
    except StopIteration:
        pass
    return 

The group_when generator takes one iterable and one predicate as parameters: it produces lists that each end in a value from the iterable where the predicate is True. If the iterable ends on a value for which the predicate returns False, yield a final list containing all the values from the one after the previous end to the last value produced by the iterable

for example:

for i in group_when('combustibles', lambda x : x in 'aeiou'):
    print(i,end='')

prints the 5 lists ['c', 'o']['m', 'b', 'u']['s', 't', 'i']['b', 'l', 'e']['s'].

my function is getting so close to the correct answer. when the input is

('combustibles', lambda x : x in 'aeiou') 

my function returns

[['c', 'o'], ['m', 'b', 'u'], ['s', 't', 'i'], ['b', 'l', 'e']] 

but the correct output should be:

[['c', 'o'], ['m', 'b', 'u'], ['s', 't', 'i'], ['b', 'l', 'e'], ['s']]

Therefore, I am only missing the last letter 's'. can anyone tell me how to fix it? many thanks

I posted the error I got below just to help you to understand my function:

 26 *Error: Failed [v for v in group_when('combustibles', lambda x : x in 'aeiou')] == [['c', 'o'], ['m', 'b', 'u'], ['s', 't', 'i'], ['b', 'l', 'e'], ['s']]
      evaluated: [['c', 'o'], ['m', 'b', 'u'], ['s', 't', 'i'], ['b', 'l', 'e']] == [['c', 'o'], ['m', 'b', 'u'], ['s', 't', 'i'], ['b', 'l', 'e'], ['s']]
 27 *Error: Failed [v for v in group_when(hide('combustibles'), lambda x : x in 'aeiou')] == [['c', 'o'], ['m', 'b', 'u'], ['s', 't', 'i'], ['b', 'l', 'e'], ['s']]
      evaluated: [['c', 'o'], ['m', 'b', 'u'], ['s', 't', 'i'], ['b', 'l', 'e']] == [['c', 'o'], ['m', 'b', 'u'], ['s', 't', 'i'], ['b', 'l', 'e'], ['s']]

Upvotes: 0

Views: 432

Answers (3)

Shasha99
Shasha99

Reputation: 1916

You code will give incorrect result when the predicate returns False for last element in iterator.

z wont be appended to d if p(y) is False for last y in iterable. You should handle that case.

Extend your code and add 2 more lines after except as mentioned below:

except StopIteration:
        pass
if len(z) !=0:
    y.append(z)

You may use the following code doing the same work:

def group_when(iterable,p):
    z = []
    d = []

    for y in iterable:
        z.append(y)
        if p(y) is True:
            d.append(z)
            z=[]
    if z:
        d.append(z)
    return d

Following is the generator version of your code:

def group_when(iterable,p):
    z = []
    for y in iterable:
        z.append(y)
        if p(y) is True:
            yield z
            z=[]
    if z :
        yield z
    return 

Upvotes: 1

bravosierra99
bravosierra99

Reputation: 1371

So going with your original form, this is how I would fix your issue.

def group_when(iterable,p):
    x = iter(iterable)
    z = []
    d = []
    for y in x:
        z.append(y)
        if p(y):
            d.append(z) 
            z = []
    if z:
        d.append(z) 
    return d   #added the d here, think OP dropped it by accident

Upvotes: 1

xZise
xZise

Reputation: 2379

The issue is that you only add z to d if you get a predicate. So if the string doesn't end with a predicate it won't add z one last time. So you need at the end somewhere:

if z:
    d.append(z)

This adds z only if it is not empty. But your code is missing yield or the actual return statement so I'm not sure where this should happen.

Also you don't need to directly compare it to the booleans. In fact you could do the following:

if p(y):
    z.append(y)
    d.append(z)
    z = []
else:
    z.append(y)

Upvotes: 1

Related Questions