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