46

I saw How to extract dictionary single key-value pair in variables suggesting:

d = {"a":1}
(k, v), = d.items()

But: I only care about the value. And I want to pass that value to a method; like:

foo(v)

So the question is: is there a simple command that works for both python2 and python3 that gives me that value directly, without the detour of the "tuple" assignment?

Or is there a way to make the tuple assignment work for my usecase of calling a method?

jpp
  • 159,742
  • 34
  • 281
  • 339
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • 3
    `v, = d.values()` works fine in both Py2 and 3, you'd obviously need to unpack before invoking the function. – Dimitris Fasarakis Hilliard Apr 26 '17 at 08:53
  • At first I thought this is simple. I mean just get the value using the key but then I got it. You do not know the key. I found this which might help: http://stackoverflow.com/questions/3097866/access-an-arbitrary-element-in-a-dictionary-in-python – Soumya Kishor Mishra Apr 26 '17 at 09:00

7 Answers7

41

list(d.values())[0] will be evaluated to 1. As pointed out in the comments, the cast to list is only needed in python3.

next(iter(d.values())) is another possibility (probably more memory efficient, as you do not need to create a list)

Both solution testes locally with python 3.6.0 and in TIO with python 2.

B. Barbieri
  • 1,055
  • 13
  • 16
14

next(iter(d.values())) is the natural way to extract the only value from a dictionary. Conversion to list just to extract the only element is not necessary.

It is also performs best of the available options (tested on Python 3.6):

d = [{'a': i} for i in range(100000)]

%timeit [next(iter(i.values())) for i in d]  # 50.1 ms per loop
%timeit [list(i.values())[0] for i in d]     # 54.8 ms per loop
%timeit [list(i.values()).pop() for i in d]  # 81.8 ms per loop
jpp
  • 159,742
  • 34
  • 281
  • 339
4

is there a way to make the tuple assignment work for my usecase

v, *_ = d.values()

Extended unpacking will do the job in Python 3, failing with a ValueError: Not enough values to unpack if d is empty. Extended unpacking is not available in Python 2.

Chris Keefe
  • 797
  • 7
  • 17
3

If you know the key then you can simply do :

d["a"] 
output :
1

and if you don't know the key:

for key in d.keys():
d[key]

#so basically you have to do :

for key in d.keys():
f00(d[key])
3

Using more_itertools.one is short, and also validates that there is a single entry

In [1]: from more_itertools import one
   ...: d = {"a":5}
   ...: one(d.values())
Out[1]: 5

Alonme
  • 1,364
  • 15
  • 28
2

is there a simple command that works for both python2 and python3 that gives me that value directly, without the detour of the "tuple" assignment?

The solution using dict.copy()(to preserve the original dict) and dict.popitem() functions:

d = {"a":1}
foo(d.copy().popitem()[1])
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
  • This the need to make a copy in order to avoid changing the original severely limits the usefulness of this approach, IMO. – martineau Jan 07 '21 at 08:08
1

For your foo(v) use case, you can directly unpack the value into the call:

foo(*d.values())

Demo:

def foo(x):
    print(x)

d = {"a": 1}

(k, v), = d.items()
foo(v)

foo(*d.values())

Output (Attempt This Online!):

1
1
Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65