Dictionary: Get list of values for list of keys
Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn
--
Music by Eric Matyas
https://www.soundimage.org
Track title: A Thousand Exotic Places Looping v001
--
Chapters
00:00 Question
00:32 Accepted answer (Score 273)
00:46 Answer 2 (Score 124)
01:27 Answer 3 (Score 69)
03:44 Answer 4 (Score 18)
04:11 Thank you
--
Full question
https://stackoverflow.com/questions/1845...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #list #dictionary #key
#avk47
--
Music by Eric Matyas
https://www.soundimage.org
Track title: A Thousand Exotic Places Looping v001
--
Chapters
00:00 Question
00:32 Accepted answer (Score 273)
00:46 Answer 2 (Score 124)
01:27 Answer 3 (Score 69)
03:44 Answer 4 (Score 18)
04:11 Thank you
--
Full question
https://stackoverflow.com/questions/1845...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #list #dictionary #key
#avk47
ACCEPTED ANSWER
Score 287
A list comprehension seems to be a good way to do this:
>>> [mydict[x] for x in mykeys]
[3, 1]
ANSWER 2
Score 129
A couple of other ways than list-comp:
- Build list and throw exception if key not found:
map(mydict.__getitem__, mykeys) - Build list with
Noneif key not found:map(mydict.get, mykeys)
Alternatively, using operator.itemgetter can return a tuple:
from operator import itemgetter
myvalues = itemgetter(*mykeys)(mydict)
# use `list(...)` if list is required
Note: in Python3, map returns an iterator rather than a list. Use list(map(...)) for a list.
ANSWER 3
Score 71
A little speed comparison:
Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Dec 7 2015, 14:10:42) [MSC v.1500 64 bit (AMD64)] on win32
In[1]: l = [0,1,2,3,2,3,1,2,0]
In[2]: m = {0:10, 1:11, 2:12, 3:13}
In[3]: %timeit [m[_] for _ in l] # list comprehension
1000000 loops, best of 3: 762 ns per loop
In[4]: %timeit map(lambda _: m[_], l) # using 'map'
1000000 loops, best of 3: 1.66 µs per loop
In[5]: %timeit list(m[_] for _ in l) # a generator expression passed to a list constructor.
1000000 loops, best of 3: 1.65 µs per loop
In[6]: %timeit map(m.__getitem__, l)
The slowest run took 4.01 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 853 ns per loop
In[7]: %timeit map(m.get, l)
1000000 loops, best of 3: 908 ns per loop
In[33]: from operator import itemgetter
In[34]: %timeit list(itemgetter(*l)(m))
The slowest run took 9.26 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 739 ns per loop
So list comprehension and itemgetter are the fastest ways to do this.
Update
For large random lists and maps I had a bit different results:
Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Dec 7 2015, 14:10:42) [MSC v.1500 64 bit (AMD64)] on win32
In[2]: import numpy.random as nprnd
l = nprnd.randint(1000, size=10000)
m = dict([(_, nprnd.rand()) for _ in range(1000)])
from operator import itemgetter
import operator
f = operator.itemgetter(*l)
%timeit f(m)
1000 loops, best of 3: 1.14 ms per loop
%timeit list(itemgetter(*l)(m))
1000 loops, best of 3: 1.68 ms per loop
%timeit [m[_] for _ in l] # list comprehension
100 loops, best of 3: 2 ms per loop
%timeit map(m.__getitem__, l)
100 loops, best of 3: 2.05 ms per loop
%timeit list(m[_] for _ in l) # a generator expression passed to a list constructor.
100 loops, best of 3: 2.19 ms per loop
%timeit map(m.get, l)
100 loops, best of 3: 2.53 ms per loop
%timeit map(lambda _: m[_], l)
100 loops, best of 3: 2.9 ms per loop
So in this case the clear winner is f = operator.itemgetter(*l); f(m), and clear outsider: map(lambda _: m[_], l) .
Update for Python 3.6.4
import numpy.random as nprnd
l = nprnd.randint(1000, size=10000)
m = dict([(_, nprnd.rand()) for _ in range(1000)])
from operator import itemgetter
import operator
f = operator.itemgetter(*l)
%timeit f(m)
1.66 ms ± 74.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit list(itemgetter(*l)(m))
2.1 ms ± 93.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit [m[_] for _ in l] # list comprehension
2.58 ms ± 88.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit list(map(m.__getitem__, l))
2.36 ms ± 60.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit list(m[_] for _ in l) # a generator expression passed to a list constructor.
2.98 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit list(map(m.get, l))
2.7 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit list(map(lambda _: m[_], l)
3.14 ms ± 62.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
So, results for Python 3.6.4 is almost the same.
ANSWER 4
Score 18
Here are three ways.
Raising KeyError when key is not found:
result = [mapping[k] for k in iterable]
Default values for missing keys.
result = [mapping.get(k, default_value) for k in iterable]
Skipping missing keys.
result = [mapping[k] for k in iterable if k in mapping]