0

I have a list of lists as shown below. I want to iterate the list and for each list item with 'yes' at index 1, I want to update index 2 with count of occurrences of 'no' before I get another yes and then add add 1 to it. I don't know how to iterate over a range with a while to stop when I encounter another yes.

I've simplified the data in the Problem and Answer below, however here is the code I was using against the object to try and accomplish.

Problem

fullchart = [
    [1, 'yes', 0],
    [2, 'no', 0],
    [3, 'no', 0],
    [4, 'yes', 0],
    [5, 'no', 0],
    [6, 'no', 0],
    [7, 'yes', 0],
    [8, 'no', 0],
    [9, 'yes', 0]
]

Expected Output

[
    [1, 'yes', 3],
    [2, 'no', 0],
    [3, 'no', 0],
    [4, 'yes', 3],
    [5, 'no', 0],
    [6, 'no', 0],
    [7, 'yes', 2],
    [8, 'no', 0],
    [9, 'yes', 1]
]

Code

end_page = 0

for i in range(len(fullchart)):
    end_page = 0
    #pprint.pprint(fullchart[i][1])
    if fullchart[i][1] == 'yes':
        for b in range(i+1, len(fullchart)):
            print(b)
            if fullchart[i+1][1] == 'no':
                end_page += 1
                print('printing end_page')
                print(end_page)
        fullchart[i][3] == end_page
    else:
        pass
1
  • Provide the input and expected output question is not clear Commented Sep 28, 2020 at 5:42

4 Answers 4

3

You can keep track of the last index with 'yes' and update the list in-place.

base_idx = 0
for i, (_, bool, _) in enumerate(L):
    if bool == 'yes':
        L[base_idx][2] = i - base_idx
        base_idx = i
L[base_idx][2] = i - base_idx + 1

print(*L, sep='\n')

Output

[1, 'yes', 3]
[2, 'no', 0]
[3, 'no', 0]
[4, 'yes', 3]
[5, 'no', 0]
[6, 'no', 0]
[7, 'yes', 2]
[8, 'no', 0]
[9, 'yes', 1]
Sign up to request clarification or add additional context in comments.

Comments

1

I think what you are looking for is break. Once you find the next "yes", then you want to capture that value and break out of the nested for loop.


fullchart = [
[1, 'yes', 0],
[2, 'no', 0],
[3, 'no', 0],
[4, 'yes', 0],
[5, 'no', 0],
[6, 'no', 0],
[7, 'yes', 0],
[8, 'no', 0],
[9, 'yes', 0]
]
end_page = 0


for i in range(len(fullchart)):
    end_page = 0
    if fullchart[i][1] == 'yes':
        print(f'checking.. i={i}')
        for b in range(i+1, len(fullchart)):
            print(f'\tchecking.. b={b}')
            if fullchart[b][1] == 'no':
                end_page += 1
                # print('printing end_page')
                # print(end_page)
            else:
                fullchart[i][2] = end_page+1
                break

    else:
        pass
print(fullchart)

Output

checking.. i=0
        checking.. b=1
        checking.. b=2
        checking.. b=3
checking.. i=3
        checking.. b=4
        checking.. b=5
        checking.. b=6
checking.. i=6
        checking.. b=7
        checking.. b=8
checking.. i=8
[[1, 'yes', 3], [2, 'no', 0], [3, 'no', 0], [4, 'yes', 3], [5, 'no', 0], [6, 'no', 0], [7, 'yes', 2], [8, 'no', 0], [9, 'yes', 0]]

2 Comments

Since your inner loop already checked the items with 'no', you could skip those items in the outer loop by changing the pointer i = b before break and changing that outer loop to while i < len(fullchart):
Break is the concept I was looking for. Thanks.
1

Instead of using while statement, why don't you use for loop and traverse through the loop from the last to the first. That way you can count for each no until you get to the yes.

This solution does the loop only once. You don't need a nested loop. It is costly and bad coding.

Here's the code to do that:

a = [
[1, 'yes', 0],
[2, 'no', 0],
[3, 'no', 0],
[4, 'yes', 0],
[5, 'no', 0],
[6, 'no', 0],
[7, 'yes', 0],
[8, 'no', 0],
[9, 'yes', 0]
]

x = len(a)
yes = 0
for i in range(-1,-x-1,-1):
    print (a[i][1])
    if a[i][1] == 'yes':
        a[i][2] = yes+1
        yes = 0
    elif a[i][1] == 'no':
        yes +=1
    print (a[i],yes)
print (a)

The output of this will be:

[[1, 'yes', 3], [2, 'no', 0], [3, 'no', 0], [4, 'yes', 3], [5, 'no', 0], [6, 'no', 0], [7, 'yes', 2], [8, 'no', 0], [9, 'yes', 1]]

Formatted way to look at the data similar to your desired result will be:

[
 [1, 'yes', 3], 
 [2, 'no',  0], 
 [3, 'no',  0], 
 [4, 'yes', 3], 
 [5, 'no',  0], 
 [6, 'no',  0], 
 [7, 'yes', 2], 
 [8, 'no',  0], 
 [9, 'yes', 1]
]

2 Comments

Reversing the list is a good idea, this reminded me of a similar answer for a forward-looking rolling window in pandas
Agree, in pandas this will be much simpler.
0

You can use itertools.groupby() to group by yes and no and some simple logic allows you get the len() of the no group to assign to the previous yes item (Note: this assumes that yes is a singular item and first), e.g.:

In []:
import itertools as it

for k, g in it.groupby(fullchart, lambda d: d[1]):
    if k == 'yes':
        y = next(g)
        y[2] = 1
    else:
        y[2] += len(list(g))

print(fullchart)

Out[]:
[[1, 'yes', 3],
 [2, 'no', 0],
 [3, 'no', 0],
 [4, 'yes', 3],
 [5, 'no', 0],
 [6, 'no', 0],
 [7, 'yes', 2],
 [8, 'no', 0],
 [9, 'yes', 1]]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.