I am a newbie to Nested Loops, and still trying to figure things out. I would like to run through two list, and append values to a new list based on some calculations on the previous two list. Ultimately, I am trying to fix the errors in the value1 lists based on the a series of values in the value2 list. However, I want to make sure if the arguments are not met from the value2 list in the nested loop that its gets flagged in my loop. Also, I apologize if I am not making myself clear:
Here are my two lists:
value1 = [199, 201, 200, 202, 204, 206, 215, 210]
value2 = [200, 203, 206]
Here is my code:
result = []
for row1 in value1:
for row2 in value2:
x = row1 - row2
if x == 0:
new_x = row1
elif x == 1:
new_x = row1 - 1
elif x == -1:
new_x = row1 + 1
else:
pass
result.append(new_x)
Now I do get okay results:
print(result)
[200, 200, 200, 203, 203, 206, 206, 206]
But notice that the last three numbers of the list are not actually met in value2. I would like to have these flagged with "ERROR". I have tried the approach below:
value1 = [199, 201, 200, 202, 204, 206, 215, 210]
value2 = [200, 203, 206]
result = []
for row1 in value1:
for row2 in value2:
x = row1 - row2
if x == 0:
new_x = row1
elif x == 1:
new_x = row1 - 1
elif x == -1:
new_x = row1 + 1
elif x > 1:
new_x = "ERROR"
elif x < -1:
new_x = "ERROR"
else:
pass
result.append(new_x)
But I end up getting this instead:
print(result)
['ERROR', 'ERROR', 'ERROR', 'ERROR', 'ERROR', 206, 'ERROR', 'ERROR']
Ultimately, I would like this:
print(result)
[200, 200, 200, 203, 203, 206, 'ERROR', 'ERROR']
What am I missing? Thank you for your time!
You run your inner loop 3 times (once for each value in value2
, but you don't do anything with that new_x
inside the loop. Only after all 3 iterations are completed do you try to append it to the list. That means the last new_x = …
that you did will override the first two. So, in other words, it doesn't matter how close the values are to 200 and 203, only how close they are to 206. Since 199
is not close to 206
, it gives you ERROR
.
I'm not entirely sure what you're trying to do, but I think you want to compare each value1
to each value2
and keep the result for the closest value2
, not the last one. In order to do that, you need to actually write code that only updates new_x
if it's closer than the previous version.
You could do that something like this:
if x == 0:
new_x = row1
elif x == 1:
if new_x != row1:
new_x = row1 - 1
… and so on, in each case testing that you haven't already set it to something "better". But that's going to get really clunky.
I think the simplest way to do this is to first calculate the minimum (by absolute) difference across all of list2
, and only then apply it. Something like:
diff = None
for row2 in value2:
x = row1 - row2
if diff is None or abs(x) < abs(diff):
diff = x
if abs(diff) <= 1:
new_x = row1 - diff
else:
new_x = "ERROR"
So, this gives you [200, 200, 200, 203, 203, 206, 'ERROR', 'ERROR']
, which seems to be what your description is asking for.
Anyway, once you've got this working, you can simplify this all quite a bit. For example, the inner loop can be written as:
diff = min((row1 - row2 for row2 in value2), key=abs)
In fact, you can rewrite the whole loop as:
diffs = (min((row1 - row2 for row2 in value2), key=abs) for row1 in value1)
result = [row1 - diff if abs(diff) <= -1 else 'ERROR'
for row1, diff in zip(value1, diffs)]