0

In Python I have to build a (long) if statement dynamically. How can I do this?

I tried the following test code to store the necessary if-statement within a string with the function "buildFilterCondition". But this doesn´t work...

Any ideas? What is going wrong? Thank you very much.

Input = [1,2,3,4,5,6,7]
Filter = [4,7]
FilterCondition = ""

def buildFilterCondition():
    global FilterCondition
    for f in Filter:
        FilterCondition = FilterCondition + "(x==" + str(f) +") | "

    #remove the last "| " sign
    FilterCondition = FilterCondition[:-2]
    print("Current Filter: " + FilterCondition)



buildFilterCondition()
for x in Input:
    if( FilterCondition ):
        print(x)

With my Function buildFilterCondition() I want to reach the following situation, because the function generates the string "(x==4) | (x==7)", but this doesn´t work:

for x in Input:
    if( (x==4) | (x==7) ):
        print(x)

The output, the result should be 4,7 (--> filtered)

The background of my question actually had a different intention than to replace an if-statement.

I need a longer multiple condition to select specific columns of a pandas dataframe.

For example:

df2=df.loc[(df['Discount1'] == 1000) & (df['Discount2'] == 2000)]

I wanted to keep the column names and the values (1000, 2000) in 2 separate lists (or dictionary) to make my code a little more "generic".

colmnHeader = ["Discount1", "Discount2"]
filterValue = [1000, 2000]

To "filter" the data frame, I then only need to adjust the lists.

How do I now rewrite the call to the .loc method so that it works for iterating over the lists?

df2=df.loc[(df[colmHeader[0] == [filterValue[0]) & (df[colmHeader[1]] == filterValue[1])]

Unfortunately, my current attempt with the following code does not work because the panda-loc function has not to be called sequentially, but in parallel.

So I need ALL the conditions from the lists directly in the .loc call.

#FILTER
colmn = ["colmn1", "colmn2", "colmn3"]
cellContent = ["1000", "2000", "3000"]

# first make sure, the lists have the same size
if( len(colmn) == len(cellContent)):
    curIdx = 0
    for curColmnName in colmn:
        df_columns= df_columns.loc[df_columns [curColmnName]==cellContent[curIdx]]
        curIdx += 1

Thank you again!

5
  • 1
    don't use globals. pass FilterCondition as a parameter and then return the modified value. Like this FilterCondition = buildFilterCondition(FilterCondition). Then your condition iterates x over input, but then your conditional just checks FilterCondition (which will not change over each iteration, since it's independent of x). What are you trying to do? can you post an example of the output you expect your code to generate for that particular input that you posted? Commented Feb 8, 2023 at 10:10
  • Rather than trying to use a string, you'd be better off using a class that can represent a simple bool expression. You could then call a method of that class, passing it a dict (or namespace) of variable bindings, to evaluate it. That would avoid the need for dynamic string parsing. Commented Feb 8, 2023 at 10:12
  • From you example it's not clear why you need to build up a filter conditions as a string. Can't you use if x in filter instead of if( FilterCondition )? Commented Feb 8, 2023 at 10:14
  • OT: I would recommend to use f-strings like this: FilterCondition += f"(x=={f}) | " Commented Feb 8, 2023 at 10:16
  • Moreover, turn FilterCondition into an empty list, update it with FilterCondition.append(f"(x=={f})"), and after the loop use ' | '.join(FilterCondition). Commented Feb 8, 2023 at 10:18

2 Answers 2

2

Use in operator

Because simple if better than complex.

inputs = [1, 2, 3, 4, 5, 6, 7]
value_filter = [4, 7]

for x in inputs:
    if x in value_filter:
        print(x, end=' ')
# 4 7
Sign up to request clarification or add additional context in comments.

Comments

1

Use operator module

With the operator module, you can build a condition at runtime with a list of operator and values pairs to test the current value.

import operator

inputs = [1, 2, 3, 4, 5, 6, 7]

# This list can be dynamically changed if you need to
conditions = [
    (operator.ge, 4),  # value need to be greater or equal to 4
    (operator.lt, 7),  # value need to be lower than 7
]

for x in inputs:
    # all to apply a and operator on all condition, use any for or
    if all(condition(x, value) for condition, value in conditions):
        print(x, end=' ')

# 4 5 6

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.