-1

I want to use dictionary.get method but to return nothing (not None) when a key is missing, is it possible without "filtering" the output:

d = {1:'a', 2:'b'}
vals = [1,2,3]

#I want the output to look like:
newvals = [d[v] for v in vals if v in d]
#newvals
#['a', 'b']

#But this will return default value which is None:
newvals2 = [d.get(v) for v in vals]
#>>> newvals2
#['a', 'b', None]

#(I know I can add this, but do I have to?)
#newvals2 = [val for val in newvals if val]
#['a', 'b']
BERA
  • 1,345
  • 3
  • 16
  • 36
  • try d[v] then d.get(v) – batuhand Dec 23 '20 at 18:00
  • 1
    There's no such thing as "nothing" in Python. `None` is the closest it gets. – Barmar Dec 23 '20 at 18:01
  • 2
    What's the issue with 1st approach? – Tarique Dec 23 '20 at 18:01
  • Nothing really, I just want to know if it is to shorten the code with d.get without getting the None returned. – BERA Dec 23 '20 at 18:03
  • 1
    What *value* do you consider "nothing" to be? What would be the hypothetical value of ``a = d.get(v)`` be? Why do you want to use the ``.get`` variant instead of the already working ``v in d`` variant? – MisterMiyagi Dec 23 '20 at 18:03
  • He's looking for a special value that the list comprehension will automatically ignore. There isn't one. – Barmar Dec 23 '20 at 18:04
  • My question is probably not well asked/defined. I just want to end up with `['a', 'b']` with the shortest possible code, and without having the code breaking when encountering a missing key – BERA Dec 23 '20 at 18:04
  • 2
    so take approach 1. There's nothing wrong with it. Btw, your vals should better be called keys, since they are keys – smed Dec 23 '20 at 18:06
  • 2
    As far as I am aware, your first approach is the best way to do this, and it is a one-liner. How does this solution not meet your requirements? – Tyler Dec 23 '20 at 18:07

2 Answers2

4

If you don’t want anything at all, don’t think there's a better way than this:

newvals2 = [d[v] for v in vals if v in d]

Edit: I missed you already tried it. Either way, this approach seems fine without any issue. Complexity of in is O(1) anyway.

Jarvis
  • 8,494
  • 3
  • 27
  • 58
1

There is no "nothing" (or undef) value in Python that is ignored by list comprehensions.

You can use a custom sentinel ("nothing") as the default of get and explicitly remove it in the same comprehension.

>>> nothing = object()
>>> newvals2 = [v for k in vals if (v := d.get(k, nothing)) is not nothing]
>>> newvals2
['a', 'b']

Note that this is a micro-optimisation, which trades fewer dict lookups for a name lookup. It is not generally better than filtering by testing whether the key is in the dict.

MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119