madik_atma
madik_atma

Reputation: 799

How to map two filtered lists with the operator 'and' and/or 'or'

I have following two lists:

advanced_filtered_list_val1 = [row for row in cleaned_list if float(row[val1]) < wert1]

advanced_filtered_list_val2 = [row for row in cleaned_list if float(row[val2]) < wert2]

How can I map the filtered lists in a list with the option and and/or or?

The data in the lists are dictionaries and I search and filter some rows in this lists. I want to filter two values on. This works fine. But how can I now map this to filter in a list?

I tried following things:

select = int(input())

#and operation
if select == 1:
    mapped_list = [row for row in advanced_filtered_list_val1 and advanced_filtered_list_val2]
    for x in mapped_list:
        print(x)
#or operation
if select == 2:
    mapped_list = [row for row in advanced_filtered_list_val1 or advanced_filtered_list_val2]
    for x in mapped_list:
        print(x)

I import the data as follows:

faelle = [{k: v for k, v in row.items()}


for row in csv.DictReader(csvfile, delimiter=";")]

I want to filter now from wert1 and wert2 and from wert1 or wert2. Thats mean on the and clause it should be on both filters true, and on the or clause it should one of wert1 or wert2 True

Upvotes: 2

Views: 85

Answers (2)

keepAlive
keepAlive

Reputation: 6665

You want to filter dictionaries contained in cleaned_list which respect either the two wert-like conditions (AND) or at least one of them (OR). What you can do is

import operator as op
ineq_1    = 'gt'
ineq_2    = 'lt'
select    = 2
andor = {
    1:lambda L: filter(
        lambda d: getattr(op,ineq_1)(float(d[val1]), wert1)
                  and getattr(op,ineq_2)(float(d[val2]), wert2),
        L
    ),
    2:lambda L: filter(
        lambda d: getattr(op,ineq_1)(float(d[val1]), wert1)
                  or getattr(op,ineq_2)(float(d[val2]), wert2),
        L
    ),
}

mapped_list = andor[select](cleaned_list)
for x in mapped_list:
    print(dict(x))

The possible choices are gt (greater than), lt (lower than), or eq.


Note that you can even make things a little bit more "dynamic" by as well using the method and_ and or_ of the python-builtin module operator. For example, doing

#Where the two following ix2-like stuffs are defined to make
# a correspondence between names one knows, and methods of the
#  module operator.
ix2conj = {
    1:'and_',
    2:'or_',
}
ix2ineq = {
    '<' :'lt',
    '==':'eq',
    '>' :'gt',
}
def my_filter(conjunction, inequality1, inequality2, my_cleaned_list):
    return filter(
        lambda d: getattr(op, ix2conj[conjunction])(
                       getattr(op, ix2ineq[inequality1])(float(d[val1]), wert1),
                       getattr(op, ix2ineq[inequality2])(float(d[val2]), wert2)
                       ),
        my_cleaned_list
        )

ineq_1    = '>'
ineq_2    = '<'
select    = 2
print(my_filter(select, ineq_1, ineq_2, cleaned_list))

Upvotes: 2

C. Feenstra
C. Feenstra

Reputation: 593

I see where you're coming from with that syntax, but that's not what the "and" and "or" keywords in python do at all. To do what you're looking for I think you'll want to use the built in type, set. You could do something like

# note that this is already the "or" one
both = list1 + [x for x in list2 if not x in list1]

# for "and"
mapped_list = [x for x in both if x in list1 and x in list2]

If you want the resultant lists to have only unique values; otherwise you could just do the same with

both = list1 + list2

Upvotes: 0

Related Questions