Python build dynamic if conditions - or/and

Viewed 4970

I have following example, where filtering from JSON format and print data:

arr = [
    {
        "EffectiveDate": "2018-05-01T00:00:00Z",
        "IncludedQuantity": 0.0,
        "MeterCategory": "VM",
        "Unit": "1 GB/Month",
        "MeterName": "P4 Disks"
    },
    {
        "EffectiveDate": "2018-03-14T00:00:00Z",
        "IncludedQuantity": 0.0,
        "MeterCategory": "Storage",
        "MeterName": "P4 Disks"
    },
    {
        "EffectiveDate": "2017-04-01T00:00:00Z",
        "IncludedQuantity": 0.0,
        "MeterCategory": "VM",
        "Unit": "1 Hour",
        "MeterName": "P4 Disks"
    }
]

def get_data(getarr):
    for data in getarr:
        if data['MeterCategory'] == "VM"\
            and data['MeterName'] == "P4 Disks"\
                and data['Unit'] == "1 GB/Month":
            print(data)

get_data(arr)

I want to dynamically specify "AND" conditions in function get_data. Let's say I want to run function get_data with these conditions:

example 1. Search only by 'MeterCategory':

if data['MeterCategory'] == "VM":

example 2. Search by 'MeterCategory' and 'MeterName':

  if data['MeterCategory'] == "VM"\
           and data['MeterName'] == "P4 Disks":

One way is to define different functions with combination of statements, but If I want to dynamically control AND operators I found only this way:

def get_data(getarr, filter_type):
    filters = None
    r1 = "obj['MeterName'] == 'P4 Disks'"
    r2 = "obj['MeterName'] == 'P4 Disks' and obj['MeterCategory'] == 'Storage'"

    if (filter_type == "filter1"): filters = r1
    if (filter_type == "filter2"): filters = r2

    data = [obj for obj in getarr if(eval(filters))]
    print(data)

get_data(arr, 'filter2')

Can you please advice. Thanks!

1 Answers

You could pass your conditions as a dictionary of keys and values. Then in your function just loop over them, if any of your conditions are not met then break the loop since this is AND logic all conditions must be true. So if any fail just break and stop checking the others.

Assuming all conditions are True the loop will complete successfully and then enter the else part of the loop meaning we can print the data since we got through all conditions successfully.

arr = [
    {
        "EffectiveDate": "2018-05-01T00:00:00Z",
        "IncludedQuantity": 0.0,
        "MeterCategory": "VM",
        "Unit": "1 GB/Month",
        "MeterName": "P4 Disks"
    },
    {
        "EffectiveDate": "2018-03-14T00:00:00Z",
        "IncludedQuantity": 0.0,
        "MeterCategory": "Storage",
        "MeterName": "P4 Disks"
    },
    {
        "EffectiveDate": "2017-04-01T00:00:00Z",
        "IncludedQuantity": 0.0,
        "MeterCategory": "VM",
        "Unit": "1 Hour",
        "MeterName": "P4 Disks"
    }
]


def get_data(getarr, conditions):
    return_data = []
    for data in getarr:
        for key, value in conditions.items():
            if key in data and data[key] != value:
                break
        else:
            return_data.append(data)
    return return_data

print(get_data(arr, {"MeterCategory": "VM", "Unit": "1 GB/Month"}))
print(get_data(arr, {"MeterCategory": "VM"}))
print(get_data(arr, {"MeterCategory": "Storage"}))

OUTPUT

[{'EffectiveDate': '2018-05-01T00:00:00Z', 'IncludedQuantity': 0.0, 'MeterCategory': 'VM', 'Unit': '1 GB/Month', 'MeterName': 'P4 Disks'}]
[{'EffectiveDate': '2018-05-01T00:00:00Z', 'IncludedQuantity': 0.0, 'MeterCategory': 'VM', 'Unit': '1 GB/Month', 'MeterName': 'P4 Disks'}, {'EffectiveDate': '2017-04-01T00:00:00Z', 'IncludedQuantity': 0.0, 'MeterCategory': 'VM', 'Unit': '1 Hour', 'MeterName': 'P4 Disks'}]
[{'EffectiveDate': '2018-03-14T00:00:00Z', 'IncludedQuantity': 0.0, 'MeterCategory': 'Storage', 'MeterName': 'P4 Disks'}]
Related