Reputation: 119
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
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
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
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