twhale
twhale

Reputation: 755

How to make an if inside a for-loop run only once?

I am trying to put items from two lists together, based on a condition, to create a third list as output. Even though I am a novice, this is relatively straightforward. However, I am trying to make one part of the loop run only once and this where I struggle. Is there a way to do this?

The data comes from a large DataFrame of text data. But I created a simplified version of the problem, to try and solve it more easily (without luck):

a = [1, 2, 3, 4, 5]
A = [4, 5]

b = []
for i in a:
    if i in A:
        b.append(3.5) # My aim is to make this line run only once
        b.append(i)
    else:
        b.append(i)
print(b)

This gives:

[1, 2, 3, 3.5, 4, 3.5, 5]

How can I get the following result?

[1, 2, 3, 3.5, 4, 5]

Upvotes: 5

Views: 10475

Answers (6)

Subham
Subham

Reputation: 411

Using sets and no tracking variable,

a = [1, 2, 3, 4, 5]
A = [4, 5]

listU = [set(a), set(A)]
b = set.union(*listU)

res = []

for i in b:
    if 3.5 not in res:
        print("loop")
        res.append(3.5)
    res.append(i)
    
print(sorted(res))


loop #proof only runs once 
[1, 2, 3, 4, 5, 3.5]

[Program finished]

Upvotes: 0

Taohidul Islam
Taohidul Islam

Reputation: 5414

All above answers are correct. But I want to add some explanation to this. In this kind of situations where you need to run a command just on inside a loop it is always good idea to use an extra variable to trace whether the is executed or not. Initialize the variable with a value. Until the variables values is unchanged we can think that the line is not executed. Using this extra variable checking won't increase much time complexity in your program like using "in" operator.

I want to add some examples here. First one using True or False:

a = [1, 2, 3, 4, 5]
A = [4, 5]

b = []
this_portion_is_executed=False
for i in a:
    if i in A and not this_portion_is_executed:
        b.append(3.5)
        b.append(i)
        this_portion_is_executed=True
    else:
        b.append(i)
print(b)

Using integer value:

a = [1, 2, 3, 4, 5]
A = [4, 5]

b = []
this_portion_is_executed=1
for i in a:
    if i in A and not this_portion_is_executed==1:
        b.append(3.5) 
        b.append(i)
        this_portion_is_executed=2
    else:
        b.append(i)
print(b)

Using String:

a = [1, 2, 3, 4, 5]
A = [4, 5]

b = []
this_portion_is_executed="not executed"
for i in a:
    if i in A and not this_portion_is_executed=="not executed":
        b.append(3.5)
        b.append(i)
        this_portion_is_executed="executed"
    else:
        b.append(i)
print(b)

Using list (weird one but working!):

a = [1, 2, 3, 4, 5]
A = [4, 5]

b = []
this_portion_is_executed_list=[]
for i in a:
    if i in A and not this_portion_is_executed: #because empty list is treated as false
        b.append(3.5) 
        b.append(i)
        this_portion_is_executed.append(3.5) #you can append any other value
    else:
        b.append(i)
print(b)

Upvotes: 1

Olivier Melançon
Olivier Melançon

Reputation: 22304

A generalized way to change the logic in your for-loop is to manually declare your iterator, you can then break from the loop and continue where you left off.

a = [1, 2, 3, 4, 5]
A = [4, 5]

b = []

iter_a = iter(a)

for i in iter_a:
    if i in A:
        b.append(3.5)
        b.append(i)
        break
    b.append(i)

b.extend(iter_a)

print(b) # [1, 2, 3, 3.5, 4, 5]

This is especially useful if the condition is more complex and your code would gain from not computing it again once encountered.

Using functions, this can be extended to any logic.

def do_something(*args):
    ...

def do_something_once(*args):
    ...

def condition(*args):
    ...

iterator = iter(...)

for i in iterator:
    if condition(i):
        do_something_once(i, ...)
        break
    do_something(i, ...)

for i in iterator:
    do_something(i, ...)

Upvotes: 2

Dux
Dux

Reputation: 1246

You could add a boolean flag for this:

a = [1, 2, 3, 4, 5]
A = [4, 5]

b = []
extend = True
for i in a:
    if i in A:
        if extend:
            b.append(3.5) # My aim is to make this line run only once
            extend = False
        b.append(i)
    else:
        b.append(i)
print(b)

Edit: Actually, if your loop is really that simple, the other answers are more elegant, since except for the first execution, the if and else clauses are equal. If they are not, however, my code is the way to go.

Upvotes: 4

saraesa
saraesa

Reputation: 46

Can you use not in?

a = [1, 2, 3, 4, 5]
A = [4, 5]

b = []
for i in a:
    if i in A and 3.5 not in b:
        b.append(3.5)
        b.append(i)
    else:
        b.append(i)
print(b)

Upvotes: 2

Lucas Amos
Lucas Amos

Reputation: 1195

You can add a Boolean value that is initialised to false and is then set to true directly after b.append(3.5) is run. If you check this value in the if statement it will only run once.

a = [1, 2, 3, 4, 5]
A = [4, 5]

b = []

ran = False
for i in a:
    if i in A and not ran:
        b.append(3.5) # My aim is to make this line run only once
        ran = True
        b.append(i)
    else:
        b.append(i)
print(b)

Upvotes: 6

Related Questions