1
cache = [['a', 'b'], ['c', 'd']]
val = 'a'
if val in [x for [x,y] in cache]:
    print(y)
else:
    print('Not found')

In the above code, I wish to have b returned as the answer. However, the result is d. How can I retrieve the matched item from this expression? Pardon me if my terminology is incorrect, I just started learning Python and list comprehensions. I prefer to use this shorthand notation as I'm not comfortably familiar with lambda expressions just yet. Another curiosity, why is the result d?

parchment
  • 4,063
  • 1
  • 19
  • 30
Hamman Samuel
  • 2,350
  • 4
  • 30
  • 41
  • This doesn't work as the list comprehension will be evaluated first before the loop. – Bhargav Rao Nov 30 '14 at 15:17
  • Why "b"? Can you please explain your logic? – Maroun Nov 30 '14 at 15:19
  • I'm finding if `a` exists within the `cache`. If it does, then I want to retrieve the corresponding sublist item that `a` is in. – Hamman Samuel Nov 30 '14 at 15:26
  • 2
    Do you only want to filter on the first item of each sublist and return the second item? Or do you want to filter on *any* item of each sublist and return the full sublist then? – poke Nov 30 '14 at 15:34
  • What is the expected result for ```val = 'a'; cache = ['b', 'a'], ['a', 'c']``` – wwii Nov 30 '14 at 15:47
  • I want to filter on the first item and return the second item, i.e. the expected result for the code by @wwii code will be `c` – Hamman Samuel Nov 30 '14 at 15:52

3 Answers3

2
[x for [x, y] in cache]

This will create a temporary list ['a', 'c'] which you use to check whether val is contained in it. The list however is never kept around, so you can’t really access it. Since this is Python 2, the variables from within the list comprehension (x and y) actually leak out of the expression, so they are still around afterwards. But as you looped through cache they will have the last values which are 'c' and 'd' respectively.

>>> [x for [x, y] in cache]
['a', 'c']
>>> x, y
('c', 'd')

Of course that’s not really helpful, and the variable leaking has been fixed in Python 3 (where both variables stay undefined after the list comprehension).

But to solve your problem, what you want to do, is to look up the x from your cache, and then return the respective y. You can do this simply by creating a dictionary that maps x to y:

>>> d = {x: y for x, y in cache}
>>> d
{'a': 'b', 'c': 'd'}
>>> if val in d:
        print(d[val])
    else:
        print('Not found')

b

If you cache always contains sublists of two elements where the first one is used to look up things, then it’s a good idea to completely switch over to dictionaries. That way, you can have the lookup in constant time (which is very useful since you want a cache to be fast), and have a lot more control over it (like avoiding duplicate/old values).

Community
  • 1
  • 1
poke
  • 369,085
  • 72
  • 557
  • 602
2

The problem is the the expression [x for [x,y] in cache] is valued as ['a','c'] before you look for a in it. and therefore, a is not related to b in it.

y contains the value of d because it the last value the was stored in y while iterating over cache

I think what you want is something like this:

cache = [['a', 'b'], ['c', 'd']]
val = 'a'
ys = [y for [x,y] in cache if val == x]
if ys:
    print(ys[0])
else:
    print('Not found')
Elisha
  • 4,811
  • 4
  • 30
  • 46
1

This should work for the list comprehension.

[y for x,y in cache if x == val]
wwii
  • 23,232
  • 7
  • 37
  • 77