delViento
delViento

Reputation: 167

for loop does not iterate correctly python

I am not sure what I am doing wrong, but my for loop doesn't work the way I want it.

import re

liste  = ["train_seg/aoi105_c1_20_A", "train_seg/aoi105_c1_30_A", "train_seg/aoi105_c1_30_B", 
          "train_seg/aoi98_c1_20_A", "train_seg/aoi98_c1_30_A", "train_seg/aoi98_c1_30_B", 
          "train_classes/aoi98_c1_20_A", "train_classes/aoi98_c1_30_A", "train_classes/aoi98_c1_30_B",
         "train_classes/aoi105_c1_20_A", "train_classes/aoi105_c1_30_A", "train_classes/aoi105_c1_30_B"]

cat = ["c1"]
seg = ["20", "30"]
com = ["A", "B"]

for x in cat:
    for y in seg:
        for z in com:
            if y == "20" and z == "B":
                continue
            #print(x,y,z)
            
            for s in liste:
                if all(a in s for a in ["aoi105", x, y, z]):
                    #print(s)
                    
                    if re.findall("train_seg", s):
                        print(s)
                        
                    if re.findall("train_classes", s):
                        print(s)
                        
                if all(a in s for a in ["aoi98", x, y, z]):
                    #print(s)

                    if re.findall("train_seg", s):
                        print(s)

                    if re.findall("train_classes", s):
                        print(s)

I want the elements of the list "liste" evaluated in the following order:

train_seg/aoi105_c1_20_A
train_classes/aoi105_c1_20_A
train_seg/aoi98_c1_20_A
train_classes/aoi98_c1_20_A

train_seg/aoi105_c1_30_A
train_classes/aoi105_c1_30_A
train_seg/aoi98_c1_30_A
train_classes/aoi98_c1_30_A

train_seg/aoi105_c1_30_B
train_classes/aoi105_c1_30_B
train_seg/aoi98_c1_30_B
train_classes/aoi98_c1_30_B

Why is every line evaluated not in the right order? I would like train_seg and train_classes to be evaluated for each number first. Thanks!

Upvotes: 0

Views: 132

Answers (2)

Roel Schroeven
Roel Schroeven

Reputation: 1822

Looping like that, with so many levels of nested loops, is a roundabout way of getting the items in the correct order. It might work by adding a second for s in liste: right before if all(a in s for a in ["aoi98", x, y, z]):.

But I think there's a much better way: explicitly sort the items in the order you need. Something like this (apologizes for bad variable naming, caused by my lack of knowledge of the problem domain):

(edited: clearer and shorter)

import re

liste  = ["train_seg/aoi105_c1_20_A", "train_seg/aoi105_c1_30_A", "train_seg/aoi105_c1_30_B", 
          "train_seg/aoi98_c1_20_A", "train_seg/aoi98_c1_30_A", "train_seg/aoi98_c1_30_B", 
          "train_classes/aoi98_c1_20_A", "train_classes/aoi98_c1_30_A", "train_classes/aoi98_c1_30_B",
         "train_classes/aoi105_c1_20_A", "train_classes/aoi105_c1_30_A", "train_classes/aoi105_c1_30_B"]

TRAIN_TYPES_ORDER = ['train_seg', 'train_classes']
AOIS_ORDER = ['aoi105', 'aoi98']
CATS_ORDER = ['c1']
SEGS_ORDER = ['20', '30']
COMS_ORDER = ['A', 'B']

def sort_key(item):
    train_type, aoi, cat, seg, com = re.fullmatch(r'(.*)/(.*)_(.*)_(.*)_(.*)', item).groups()
    return (
        COMS_ORDER.index(com),
        SEGS_ORDER.index(seg),
        CATS_ORDER.index(cat),
        AOIS_ORDER.index(aoi),
        TRAIN_TYPES_ORDER.index(train_type),
    )

sorted_items = sorted(liste, key=sort_key)
for item in sorted_items:
    print(item)

Upvotes: 0

Daniel Paul
Daniel Paul

Reputation: 514

answer is very simple. u almost got it working. u added extra print statement, that was causing the problem

import re

cat = ["c1"]
seg = ["20", "30"]
com = ["A", "B"]
tag = ["aoi105","aoi98"]
for x in cat:
    for y in seg:
        for z in com:
            for i in tag:
                if y == "20" and z == "B":
                    continue            
                for s in liste:                    
                    train_seg = f'''train_seg/{i}_{x}_{y}_{z}'''
                    train_classes = f'''train_classes/{i}_{x}_{y}_{z}'''
                    if re.findall(train_seg, s): print(s)                        
                    if re.findall(train_classes, s): print(s)

Upvotes: 1

Related Questions