0
needs_eval = "((abc or def) and ghi)"

dict_group = {abc: ['gh@ab.com', 'ab@ab.com', 'ij@ab.com'], def: ['ab@ab.com', 'cd@ab.com', 'ef@ab.com'], ghi: ['cd@ab.com', 'ab@ab.com', 'kl@ab.com', 'gh@ab.com']}

for k,v in dict_group.iteritems():
    str_v=str(v[0])
    needs_eval = needs_eval.replace("and", "&").replace("or", "|").replace(k,str_v)
#needs_eval = re.sub(k,v[0],needs_eval)
print(list(eval(needs_eval)))

O/p i get: ((['gh@ab.com', 'ab@ab.com', 'ij@ab.com'] | ['ab@ab.com', 'cd@ab.com', 'ef@ab.com']) & ['cd@ab.com', 'ab@ab.com', 'kl@ab.com', 'gh@ab.com'])

When i evaluate "needs_eval" i want the logical output "['cd@ab.com', 'ab@ab.com', 'gh@ab.com']"

I am converting the dict "value" into a string before substituting it into the "needs_eval" string because "replace or re.sub" only passes strings.

ManyuBishnoi
  • 339
  • 5
  • 9
  • 3
    You need to make this more clear, I don't think it's fair to make people read through your code and figure out what you're trying to do without some guidance. From what I see, that dictionary declaration should throw an error because abc, def, and ghi are not declared anywhere. – CasualScience Mar 16 '16 at 05:37
  • How do you get `kl@ab.com` in the expected output? – AChampion Mar 16 '16 at 06:27
  • Thanks guys for pointing the wrong code. I have removed the bottom section and changed the expected o/p. – ManyuBishnoi Mar 16 '16 at 06:44
  • And further, why are you using `eval`? This seems like the paramount of an [xy problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What are you actually trying to do? I have a strong inkling that there's a better solution than `eval`... – Jared Goguen Mar 16 '16 at 06:47

2 Answers2

1

The operators | and & are only defined on set not list, so you need to change your dict_group to be a dictionary of sets, e.g.:

needs_eval = "((abc or def) and ghi)"
dict_group = {'abc': {'gh@ab.com', 'ab@ab.com', 'ij@ab.com'},
              'def': {'ab@ab.com', 'cd@ab.com', 'ef@ab.com'}, 
              'ghi': {'cd@ab.com', 'ab@ab.com', 'kl@ab.com', 'gh@ab.com'}}

>>> for k,v in dict_group.items():
...     needs_eval = needs_eval.replace("and", "&").replace("or", "|").replace(k,str(v))
>>> list(eval(needs_eval))
['cd@ab.com', 'ab@ab.com', 'gh@ab.com']

Not sure why you need to convert to a list if all you need is the set of values that meet the conditions:

>>> eval(needs_eval)
{'ab@ab.com', 'cd@ab.com', 'gh@ab.com'}
AChampion
  • 29,683
  • 4
  • 59
  • 75
  • Perfect, this works. Since this dictionary (dict_group) is created at run time and used at other places as well so i dont want to change it to be a set. But below is the code change that made it work fine : str_v=str(set(v[0])) – ManyuBishnoi Mar 16 '16 at 06:51
0

I don't think the 'AND's and 'OR's are doing what you thing they are when comparing lists.

After playing around with this (never knew this wasn't a syntax error before just now) and reading this post, it appears that:

AND with two lists that evaluate to True returns the right operand

OR with two lists that evaluate to True returns the left operand

Because you're lists have items, they'll always evaluate to True. Your output is only happening because of the order in which you apply (and group) the 'AND's and 'OR's to your lists.

The gnarly bug that will inevitably bit you is - if you attempt to iterate the dictionary to generate your list values, you will get non-deterministic behavior. This is because dictionaries do not guarantee order, so sometimes you'll get different output for "no apparent reason".

I would strong suggest to not rely on the 'and' and 'or' operators for your lists.

Community
  • 1
  • 1
willnx
  • 1,253
  • 1
  • 8
  • 14
  • The OP is changing the `and` and `or` to `&` and `|`, which are defined on sets. And does give the answer expected... – AChampion Mar 16 '16 at 06:04
  • The askers snippet at the end of their post where they manually run it, and it works is just using lists -> that's what lead to my concern b/c it's just returning the right most list, and that's being defined as their expected behavior. – willnx Mar 16 '16 at 06:24
  • Ahh, yes. Didn't notice that - as you point out that just returns the last list. – AChampion Mar 16 '16 at 06:27