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?

Asked By: fj123x

||

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'
Answered By: Martijn Pieters

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).

Answered By: Mark
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

Answered By: pranav dua

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.

Answered By: gerrit

I wanted “key” & “value” pair of a first dictionary item. I used the following code.

 key, val = next(iter(my_dict.items()))
Answered By: Sheikh Abdul Wahid

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

Answered By: woodz

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)
Answered By: not a robot
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.