Accessing dict_keys element by index in Python3
Question:
I’m trying to access a dict_key’s element by its index:
test = {'foo': 'bar', 'hello': 'world'}
keys = test.keys() # dict_keys object
keys.index(0)
AttributeError: 'dict_keys' object has no attribute 'index'
I want to get foo
.
same with:
keys[0]
TypeError: 'dict_keys' object does not support indexing
How can I do this?
Answers:
Call list()
on the dictionary instead:
keys = list(test)
In Python 3, the dict.keys()
method returns a dictionary view object, which acts as a set. Iterating over the dictionary directly also yields keys, so turning a dictionary into a list results in a list of all the keys:
>>> test = {'foo': 'bar', 'hello': 'world'}
>>> list(test)
['foo', 'hello']
>>> list(test)[0]
'foo'
Not a full answer but perhaps a useful hint. If it is really the first item you want*, then
next(iter(q))
is much faster than
list(q)[0]
for large dicts, since the whole thing doesn’t have to be stored in memory.
For 10.000.000 items I found it to be almost 40.000 times faster.
*The first item in case of a dict being just a pseudo-random item before Python 3.6 (after that it’s ordered in the standard implementation, although it’s not advised to rely on it).
test = {'foo': 'bar', 'hello': 'world'}
ls = []
for key in test.keys():
ls.append(key)
print(ls[0])
Conventional way of appending the keys to a statically defined list and then indexing it for same
In many cases, this may be an XY Problem. Why are you indexing your dictionary keys by position? Do you really need to? Until recently, dictionaries were not even ordered in Python, so accessing the first element was arbitrary.
I just translated some Python 2 code to Python 3:
keys = d.keys()
for (i, res) in enumerate(some_list):
k = keys[i]
# ...
which is not pretty, but not very bad either. At first, I was about to replace it by the monstrous
k = next(itertools.islice(iter(keys), i, None))
before I realised this is all much better written as
for (k, res) in zip(d.keys(), some_list):
which works just fine.
I believe that in many other cases, indexing dictionary keys by position can be avoided. Although dictionaries are ordered in Python 3.7, relying on that is not pretty. The code above only works because the contents of some_list
had been recently produced from the contents of d
.
Have a hard look at your code if you really need to access a disk_keys
element by index. Perhaps you don’t need to.
I wanted “key” & “value” pair of a first dictionary item. I used the following code.
key, val = next(iter(my_dict.items()))
Python 3
mydict = {'a': 'one', 'b': 'two', 'c': 'three'}
mykeys = [*mydict] #list of keys
myvals = [*mydict.values()] #list of values
print(mykeys)
print(myvals)
Output
['a', 'b', 'c']
['one', 'two', 'three']
Also see this detailed answer
If you need to slice dictionary keys (not just the first key), instead of calling list()
on test
, generalize the method in Mark’s answer using islice
from the built-in itertools
module.
from itertools import islice
# slice test.keys from index l to index u
some_keys = list(islice(test, l, u))
Depending on the size of the slice relative to the size of the dictionary, this method is 50% to >40000x faster than
list(test)[l:u]
For example, in the example below, it’s >43000x faster.
n = 10_000_000
test = dict(zip(range(n), [0,1,2,3,4]*(n//5)))
%timeit list(islice(test, 10, 30))
# 4.43 µs ± 193 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit list(test)[10:30]
# 192 ms ± 2.65 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
I’m trying to access a dict_key’s element by its index:
test = {'foo': 'bar', 'hello': 'world'}
keys = test.keys() # dict_keys object
keys.index(0)
AttributeError: 'dict_keys' object has no attribute 'index'
I want to get foo
.
same with:
keys[0]
TypeError: 'dict_keys' object does not support indexing
How can I do this?
Call list()
on the dictionary instead:
keys = list(test)
In Python 3, the dict.keys()
method returns a dictionary view object, which acts as a set. Iterating over the dictionary directly also yields keys, so turning a dictionary into a list results in a list of all the keys:
>>> test = {'foo': 'bar', 'hello': 'world'}
>>> list(test)
['foo', 'hello']
>>> list(test)[0]
'foo'
Not a full answer but perhaps a useful hint. If it is really the first item you want*, then
next(iter(q))
is much faster than
list(q)[0]
for large dicts, since the whole thing doesn’t have to be stored in memory.
For 10.000.000 items I found it to be almost 40.000 times faster.
*The first item in case of a dict being just a pseudo-random item before Python 3.6 (after that it’s ordered in the standard implementation, although it’s not advised to rely on it).
test = {'foo': 'bar', 'hello': 'world'}
ls = []
for key in test.keys():
ls.append(key)
print(ls[0])
Conventional way of appending the keys to a statically defined list and then indexing it for same
In many cases, this may be an XY Problem. Why are you indexing your dictionary keys by position? Do you really need to? Until recently, dictionaries were not even ordered in Python, so accessing the first element was arbitrary.
I just translated some Python 2 code to Python 3:
keys = d.keys()
for (i, res) in enumerate(some_list):
k = keys[i]
# ...
which is not pretty, but not very bad either. At first, I was about to replace it by the monstrous
k = next(itertools.islice(iter(keys), i, None))
before I realised this is all much better written as
for (k, res) in zip(d.keys(), some_list):
which works just fine.
I believe that in many other cases, indexing dictionary keys by position can be avoided. Although dictionaries are ordered in Python 3.7, relying on that is not pretty. The code above only works because the contents of some_list
had been recently produced from the contents of d
.
Have a hard look at your code if you really need to access a disk_keys
element by index. Perhaps you don’t need to.
I wanted “key” & “value” pair of a first dictionary item. I used the following code.
key, val = next(iter(my_dict.items()))
Python 3
mydict = {'a': 'one', 'b': 'two', 'c': 'three'}
mykeys = [*mydict] #list of keys
myvals = [*mydict.values()] #list of values
print(mykeys)
print(myvals)
Output
['a', 'b', 'c']
['one', 'two', 'three']
Also see this detailed answer
If you need to slice dictionary keys (not just the first key), instead of calling list()
on test
, generalize the method in Mark’s answer using islice
from the built-in itertools
module.
from itertools import islice
# slice test.keys from index l to index u
some_keys = list(islice(test, l, u))
Depending on the size of the slice relative to the size of the dictionary, this method is 50% to >40000x faster than
list(test)[l:u]
For example, in the example below, it’s >43000x faster.
n = 10_000_000
test = dict(zip(range(n), [0,1,2,3,4]*(n//5)))
%timeit list(islice(test, 10, 30))
# 4.43 µs ± 193 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit list(test)[10:30]
# 192 ms ± 2.65 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)