591

If a mydict is not empty, I access an arbitrary element as:

mydict[mydict.keys()[0]]

Is there any better way to do this?

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Stan
  • 37,207
  • 50
  • 124
  • 185
  • 3
    What he said.. this is only really a valid question if there's only one element in the dict, or you don't care which you get back. – royal Jun 22 '10 at 23:27
  • 6
    Yup, I just need to access to whatever element in the dict, so that's why I want to access to first element. – Stan Jun 23 '10 at 00:00
  • 2
    @Stan: but as Greg said, there is no definite "first" element in dict. so maybe you should change your question, just to be clear – tdihp Dec 05 '12 at 11:28
  • 11
    I think it is a valid question. If you need to access an arbitrary element, and you are sure that the dict is not empty, it may be a good idea to ask for the "first", because the number of items may not be known. – kap Jul 07 '15 at 10:13
  • Perhaps the question should also be rephrased, access the first "value" in dict, since the code example is actually retrieving the value. I would take "element" here to mean key / value pair. In either case, next(iter(dict.keys())) provides a key entry, and next(iter(dict.values())) would provide a value - assuming here we have a dictionary with one entry and using Python 3 – arcseldon Nov 27 '15 at 11:35
  • The code in this question doesn't seem to work in Python 3. `d = {'foo':'bar'}` `d[d.keys()[0]]` 'TypeError: 'dict_keys' object does not support indexing' – Michael Scheper Jul 21 '17 at 20:31
  • 12
    @MichaelScheper You have to cast to list : `list(mydict.keys())[0]`. – Daniel Moskovich Aug 03 '18 at 05:22
  • tuple(mydict.keys())[0] also works. – raz Jan 31 '22 at 12:25

14 Answers14

685

On Python 3, non-destructively and iteratively:

next(iter(mydict.values()))

On Python 2, non-destructively and iteratively:

mydict.itervalues().next()

If you want it to work in both Python 2 and 3, you can use the six package:

six.next(six.itervalues(mydict))

though at this point it is quite cryptic and I'd rather prefer your code.

If you want to remove any item, do:

key, value = mydict.popitem()

Note that "first" may not be an appropriate term here because dict is not an ordered type in Python < 3.6. Python 3.6+ dicts are ordered.

gmelodie
  • 411
  • 4
  • 18
178

If you only need to access one element (being the first by chance, since dicts do not guarantee ordering) you can simply do this in Python 2:

my_dict.keys()[0]    # key of "first" element
my_dict.values()[0]  # value of "first" element
my_dict.items()[0]   # (key, value) tuple of "first" element

Please note that (at best of my knowledge) Python does not guarantee that 2 successive calls to any of these methods will return list with the same ordering. This is not supported with Python3.

in Python 3:

list(my_dict.keys())[0]    # key of "first" element
list(my_dict.values())[0]  # value of "first" element
list(my_dict.items())[0]   # (key, value) tuple of "first" element
tony
  • 870
  • 7
  • 16
swK
  • 2,050
  • 1
  • 15
  • 9
  • 100
    That only works in Python 2.x, for 3.x you have to use `list(my_dict.keys())[0]` – alldayremix Oct 08 '13 at 03:39
  • 11
    So, what complexity class is this? Surely, `list(my_dict.keys())[0]` is not lazy? – Evgeni Sergeev Aug 06 '16 at 11:33
  • 1
    To clarify, what @alldayremix meant with that comment is in python 3.x my_dict.function() results do not support indexing, this is why first of all we must convert it into a list and then we can use the index [0] – Noki May 24 '19 at 09:41
  • 1
    @EvgeniSergeev I suppose it has linear complexity both to the time and space - highly inefficient. I can't imagine how this can be lazy - there's a list constructor call... that probably goes for the Python 2 solution as well, from docs `Return a copy of the dictionary’s list of values.` - the reason why they changed it in Python 3, and why subscription is no longer valid – Jiří Dec 11 '20 at 15:26
  • 1
    would like to pinpoint that to call `list(my_dict.keys())[0]` is basically against the python 3 `values()` behaviour intention - consider: `for val in d.values(): break` - in python 3 this is O(1) whereas in python 2 this copies whole values list - O(n) - only to discard it... this answer copies the whole list to get only one of it's values – Jiří Dec 11 '20 at 15:34
  • The list operation returns a reordered version of the dict keys, so when you access the first element it may be not the same of the starting dict – Aelius Aug 24 '21 at 15:04
60

In python3, The way :

dict.keys() 

return a value in type : dict_keys(), we'll got an error when got 1st member of keys of dict by this way:

dict.keys()[0]
TypeError: 'dict_keys' object does not support indexing

Finally, I convert dict.keys() to list @1st, and got 1st member by list splice method:

list(dict.keys())[0]
Xb74Dkjb
  • 982
  • 9
  • 20
27

to get a key

next(iter(mydict))

to get a value

next(iter(mydict.values()))

to get both

next(iter(mydict.items())) # or next(iter(mydict.viewitems())) in python 2

The first two are Python 2 and 3. The last two are lazy in Python 3, but not in Python 2.

drkostas
  • 517
  • 1
  • 7
  • 29
maxbellec
  • 16,093
  • 10
  • 36
  • 43
17

As others mentioned, there is no "first item", since dictionaries have no guaranteed order (they're implemented as hash tables). If you want, for example, the value corresponding to the smallest key, thedict[min(thedict)] will do that. If you care about the order in which the keys were inserted, i.e., by "first" you mean "inserted earliest", then in Python 3.1 you can use collections.OrderedDict, which is also in the forthcoming Python 2.7; for older versions of Python, download, install, and use the ordered dict backport (2.4 and later) which you can find here.

Python 3.7 Now dicts are insertion ordered.

rominf
  • 2,719
  • 3
  • 21
  • 39
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
12

Ignoring issues surrounding dict ordering, this might be better:

next(dict.itervalues())

This way we avoid item lookup and generating a list of keys that we don't use.

Python3

next(iter(dict.values()))
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
12

How about, this. Not mentioned here yet.

py 2 & 3

a = {"a":2,"b":3}
a[list(a)[0]] # the first element is here
>>> 2
Mikhail_Sam
  • 10,602
  • 11
  • 66
  • 102
animaacija
  • 170
  • 9
  • 25
8

In python3

list(dict.values())[0]
Oleg Matei
  • 866
  • 13
  • 9
3
first_key, *rest_keys = mydict
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • 14
    Thank you for this code snippet, which might provide some limited, immediate help. A [proper explanation would greatly improve its long-term value](//meta.stackexchange.com/q/114762/206345) by showing _why_ this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you've made. – Suraj Rao Feb 18 '19 at 12:37
2

For both Python 2 and 3:

import six

six.next(six.itervalues(d))
oblalex
  • 5,366
  • 2
  • 24
  • 25
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. – Martin Tournoij Jan 07 '15 at 14:00
  • This exactly answers the question `Is there any better way to do this?` in short manner. – oblalex Jan 07 '15 at 14:41
  • 1
    This answer has been given twice already, one of which has been on this site for almost 5 years. This is a comment on another answer (as in: *here's how to improve the answer to make it work with both Python 2 & 3*), and not a "new" answer, as such. SO's review system automatically placed a somewhat unhelpful note in this case... – Martin Tournoij Jan 07 '15 at 14:49
  • No, sir. You added this variant to your 5 y.o. answer just 17 hours ago, 1 hour after I wrote this answer. Try to use 'find' on this page for 'six' word and you will find only 6 matches only in these 2 answers. Anyway, does this answer really disturb you? I think this might help other people in future and this is OK. So, what's the deal? – oblalex Jan 08 '15 at 07:50
  • That's because IMHO this answer should have been an edit to that post in the first place. Without the edit, people would have to scroll a number of pages down to see your answer; do you think that's more useful than editing a highly upvoted answer which is almost exactly the same as yours? – Martin Tournoij Jan 08 '15 at 07:53
  • Well, now I see, thanks. Sorry, I didn't know I can edit answers of other people. Next time I'll do so. – oblalex Jan 08 '15 at 07:56
2

You can always do:

for k in sorted(d.keys()):
    print d[k]

This will give you a consistently sorted (with respect to builtin.hash() I guess) set of keys you can process on if the sorting has any meaning to you. That means for example numeric types are sorted consistently even if you expand the dictionary.

EXAMPLE

# lets create a simple dictionary
d = {1:1, 2:2, 3:3, 4:4, 10:10, 100:100}
print d.keys()
print sorted(d.keys())

# add some other stuff
d['peter'] = 'peter'
d['parker'] = 'parker'
print d.keys()
print sorted(d.keys())

# some more stuff, numeric of different type, this will "mess up" the keys set order
d[0.001] = 0.001
d[3.14] = 'pie'
d[2.71] = 'apple pie'
print d.keys()
print sorted(d.keys())

Note that the dictionary is sorted when printed. But the key set is essentially a hashmap!

Darren
  • 68,902
  • 24
  • 138
  • 144
1

Another way to do this in one line while keeping the dictionary intact is:

arbitrary_value = mydict.setdefault(*mydict.popitem())

popitem() returns a tuple of (key, value) for the last item that was added into the dictionary and this pair is passed into setdefault as positional arguments. The setdefault tries to insert key into mydict with value value if it doesn't already exist, but does nothing if does exist; and then returns the value of that key to the caller. Because we already popped the (key, value) pair out of the dictionary, we insert it back into it via setdefault and then proceed to return value, which is what we want.

LurkerZ
  • 92
  • 4
0

No external libraries, works on both Python 2.7 and 3.x:

>>> list(set({"a":1, "b": 2}.values()))[0]
1

For aribtrary key just leave out .values()

>>> list(set({"a":1, "b": 2}))[0]
'a'
Thomas Browne
  • 23,824
  • 32
  • 78
  • 121
-2

Subclassing dict is one method, though not efficient. Here if you supply an integer it will return d[list(d)[n]], otherwise access the dictionary as expected:

class mydict(dict):
    def __getitem__(self, value):
        if isinstance(value, int):
            return self.get(list(self)[value])
        else:
            return self.get(value)

d = mydict({'a': 'hello', 'b': 'this', 'c': 'is', 'd': 'a',
            'e': 'test', 'f': 'dictionary', 'g': 'testing'})

d[0]    # 'hello'
d[1]    # 'this'
d['c']  # 'is'
jpp
  • 159,742
  • 34
  • 281
  • 339