VanioMiranda
VanioMiranda

Reputation: 3

Loop in a list of tuples joining elements of each tuple

I have been trying to make this code better/faster and more sustainable but didn't succeed to do improve it yet.

Basically I need to loop in a list of tuples, and concatenate each element of the tuple with the dataframe filter expression exactly as showed in the solution. However the tuples in my list don't have the same length and they can change and have different length time to time, sometimes I can get tuples with less than 4 elements in each, other times more than 6 or even 7/8 and so on.

My solution works but I will need to edit every time the length of my tuples increases, and I know isn't the most efficient solution. How would I iterate inside the tuples using the length of each tuple in my favor in order to avoid nested ifs?

Appreciate your advises and comments

Actual list:

 Comb = [(),
 ('RD00',),
 ('RDC2',),
 ('RDC3',),
 ('RDC4',),
 ('RD00', 'RDC2'),
 ('RD00', 'RDC3'),
 ('RD00', 'RDC4'),
 ('RDC2', 'RDC3'),
 ('RDC2', 'RDC4'),
 ('RDC3', 'RDC4'),
 ('RD00', 'RDC2', 'RDC3'),
 ('RD00', 'RDC2', 'RDC4'),
 ('RD00', 'RDC3', 'RDC4'),
 ('RDC2', 'RDC3', 'RDC4'),
 ('RD00', 'RDC2', 'RDC3', 'RDC4')]

I came up with this Solution, i need to concatenate the tuples elements in each tuple and add the expression in front of each element in the tuple:

 for p in comb:
    if len(p) == 1:
        print(''"(fF2_Principal['Messagetype']=="'{}'.format("'"+p[0]+"')"))
    if len(p) == 2:
        print(''"(fF2_Principal['Messagetype']=="'{} & '"   (fF2_Principal['Messagetype']=="'{}'.format("'"+p[0]+"')", "'"+p[1]+"')"))
    elif len(p) == 3:
        print(''"(fF2_Principal['Messagetype']=="'{} & '"(fF2_Principal['Messagetype']=="'{} & '"(fF2_Principal['Messagetype']=="'{}'.format("'"+p[0]+"')", "'"+p[1]+"')","'"+p[2]+"')"))
    elif len(p) == 4:
        print(''"(fF2_Principal['Messagetype']=="'{} & '"(fF2_Principal['Messagetype']=="'{} & '" (fF2_Principal['Messagetype']=="'{} & '"(fF2_Principal['Messagetype']=="'{}'.format("'"+p[0]+"')", "'"+p[1]+"')","'"+p[2]+"')","'"+p[3]+"')"))
    elif len(p) == 5: # not done yet, my previous data had 5 elements in one tuple
        print('{} : {} : {} : {} : {}'.format(p[0], p[1],p[2],p[3],p[4])) 

The code above generates the following results, which works for my purpose, however I cant be monitoring the data to see when a different length of tuples will be present.
Results:

    (fF2_Principal['Messagetype']=='RD00')
    (fF2_Principal['Messagetype']=='RDC2')
    (fF2_Principal['Messagetype']=='RDC3')
    (fF2_Principal['Messagetype']=='RDC4')
    (fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC2')
    (fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC3')
    (fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC4')
    (fF2_Principal['Messagetype']=='RDC2') & (fF2_Principal['Messagetype']=='RDC3')
    (fF2_Principal['Messagetype']=='RDC2') & (fF2_Principal['Messagetype']=='RDC4')
    (fF2_Principal['Messagetype']=='RDC3') & (fF2_Principal['Messagetype']=='RDC4')
    (fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC2') & 
    (fF2_Principal['Messagetype']=='RDC3')
    (fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC2') & 
    (fF2_Principal['Messagetype']=='RDC4')
    (fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC3') & 
    (fF2_Principal['Messagetype']=='RDC4')
    (fF2_Principal['Messagetype']=='RDC2') & (fF2_Principal['Messagetype']=='RDC3') & 
    (fF2_Principal['Messagetype']=='RDC4')
    (fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC2') & 
    (fF2_Principal['Messagetype']=='RDC3') & (fF2_Principal['Messagetype']=='RDC4')

Really appreciate your comments and advises in how to improve this code and make it more sustainable.

Upvotes: 0

Views: 245

Answers (1)

Green Cloak Guy
Green Cloak Guy

Reputation: 24691

The easiest way to do this is using a list comprehension (to write each entry in the tuple's text individually) along with str.join() to patch an arbitrary number of them together.

>>> for tup in Comb:
...     msg = " & ".join(
...         f"(fF2_Principal['Messagetype']=='{e}')" for e in tup
...     )
...     print(msg)
...

(fF2_Principal['Messagetype']=='RD00')
(fF2_Principal['Messagetype']=='RDC2')
(fF2_Principal['Messagetype']=='RDC3')
(fF2_Principal['Messagetype']=='RDC4')
(fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC2')
(fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC3')
(fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC4')
(fF2_Principal['Messagetype']=='RDC2') & (fF2_Principal['Messagetype']=='RDC3')
(fF2_Principal['Messagetype']=='RDC2') & (fF2_Principal['Messagetype']=='RDC4')
(fF2_Principal['Messagetype']=='RDC3') & (fF2_Principal['Messagetype']=='RDC4')
(fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC2') & (fF2_Principal['Messagetype']=='RDC3')
(fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC2') & (fF2_Principal['Messagetype']=='RDC4')
(fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC3') & (fF2_Principal['Messagetype']=='RDC4')
(fF2_Principal['Messagetype']=='RDC2') & (fF2_Principal['Messagetype']=='RDC3') & (fF2_Principal['Messagetype']=='RDC4')
(fF2_Principal['Messagetype']=='RD00') & (fF2_Principal['Messagetype']=='RDC2') & (fF2_Principal['Messagetype']=='RDC3') & (fF2_Principal['Messagetype']=='RDC4')

You'll note that this produces an empty line for the first element. If you don't want to print anything, even an empty line, then you can add if len(e) > 0 to the end of the comprehension, right after for e in tup, which will filter tuples out if they contain 0 elements.

Upvotes: 4

Related Questions