453

I am trying to get my program to print out "banana" from the dictionary. What would be the simplest way to do this?

This is my dictionary:

prices = {
    "banana" : 4,
    "apple" : 2,
    "orange" : 1.5,
    "pear" : 3
}
user2357112
  • 260,549
  • 28
  • 431
  • 505
slagoy
  • 4,539
  • 2
  • 11
  • 4
  • 2
    Do you want to print literally the word "banana" or the value associated with "banana" (4, in this case)? – Paul H May 21 '15 at 00:16
  • `to print out banana with a FOR loop, so when I run it, each key would also be printed out` Do you mean `for k in prices: print k`? That will print out all keys in the dictionary. – David Robinson May 21 '15 at 13:16
  • see http://stackoverflow.com/questions/3097866/python-access-to-first-element-in-dictionary – luca May 20 '16 at 12:19
  • 21
    to the first comment: in python 3.6+ dictionariesare ordered (see https://stackoverflow.com/questions/39980323/are-dictionaries-ordered-in-python-3-6) – Egirus Ornila Jan 14 '20 at 17:46

12 Answers12

606

On a Python version where dicts actually are ordered, you can do

my_dict = {'foo': 'bar', 'spam': 'eggs'}
next(iter(my_dict)) # outputs 'foo'

For dicts to be ordered, you need Python 3.7+, or 3.6+ if you're okay with relying on the technically-an-implementation-detail ordered nature of dicts on CPython 3.6.

For earlier Python versions, there is no "first key", but this will give you "a key", especially useful if there is only one.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
maxbellec
  • 16,093
  • 10
  • 36
  • 43
  • 83
    If you want both key and value in Python 3: `next(iter( my_dict.items() ))` – Jonathan H Sep 06 '18 at 09:16
  • 4
    @RyanHaining Python dicts are ordered by insertion starting with CPython 3.6 and any other Python implementation starting with Python 3.7 – Boris Verkhovskiy Dec 06 '19 at 17:24
  • not thread safe solution. If `my_dict` changed between `next` and `iter`, `next` will fail. `list(my_dict.keys())` is thread safe operation. – iperov Aug 26 '22 at 07:49
  • @iperov: Thread-safe (on CPython with GIL protection anyway), but incredibly inefficient for large `dict`s since it has to shallow copy all the keys (also, the `.keys()` is pointless, `list(my_dict)` would do the job more directly). As a practical matter, `for k in my_dict: break` would leave the first key in `k` and I believe the CPython GIL will not swap between the conversion to iterator and pulling the first value (that said, when the GIL can swap is an implementation detail that could change between CPython releases). – ShadowRanger Dec 02 '22 at 00:23
  • @ShadowRanger not a thread-safe on CPython. GIL gaurantees to lock only single byte-code. next(iter()) - is more than one byte code. – iperov Dec 02 '22 at 12:19
  • @iperov: I wasn't saying `next(iter(my_dict))` was thread-safe. I was saying that `for k in my_dict: break` will get the first element in a thread-safe way based on implementation details of the CPython GIL. Specifically, in the implementation for 3.11 at least, it doesn't check for forcibly swapping the GIL between *all* opcodes, only two specific ones (`RESUME`, a tracing no-op instruction, and `JUMP_BACKWARDS`, used by loops), plus the suite of `CALL_*` opcodes. – ShadowRanger Dec 02 '22 at 18:45
  • `for k in my_dict: break` involves just two opcodes to extract the item from a `dict` on the stack to the first key on the stack, `GET_ITER` and `FOR_ITER`. The only way for it to be thread unsafe is if the GIL can be handed off after `GET_ITER` and before the `FOR_ITER`. The check that enables forcible GIL hand-off between opcodes (reading the `eval_breaker` flag) isn't checked before or after either opcodes, and the process of creating and advancing a `dict` iterator doesn't manually release the GIL, so, *strictly as an implementation detail*, it's impossible for the GIL to be taken midway. – ShadowRanger Dec 02 '22 at 18:50
  • @iperov: To be clear, in the pre-redesign GIL, your simplistic view of when the GIL could be handed off was correct. There was an opcode counter; each time the eval loop looped back to the top, the counter was decremented; if it dropped below zero, the GIL was almost always released, so the GIL could be handed off at almost any time. The improved GIL from 3.2 started separating which opcodes checked for handoff and which didn't (based on whether they called `DISPATCH` or `FAST_DISPATCH` after processing), and over time eventually settled on the very limited set of checked opcodes used now. – ShadowRanger Dec 02 '22 at 19:05
265

A dictionary is not indexed, but it is in some way, ordered. The following would give you the first existing key:

list(my_dict.keys())[0]
cheazy
  • 189
  • 7
ylnor
  • 4,531
  • 2
  • 22
  • 39
100

Update: as of Python 3.7, insertion order is maintained, so you don't need an OrderedDict here. You can use the below approaches with a normal dict

Changed in version 3.7: Dictionary order is guaranteed to be insertion order. This behavior was an implementation detail of CPython from 3.6.

source


Python 3.6 and earlier*

If you are talking about a regular dict, then the "first key" doesn't mean anything. The keys are not ordered in any way you can depend on. If you iterate over your dict you will likely not get "banana" as the first thing you see.

If you need to keep things in order, then you have to use an OrderedDict and not just a plain dictionary.

import collections
prices  = collections.OrderedDict([
    ("banana", 4),
    ("apple", 2),
    ("orange", 1.5),
    ("pear", 3),
])

If you then wanted to see all the keys in order you could do so by iterating through it

for k in prices:
    print(k)

You could, alternatively put all of the keys into a list and then work with that

keys = list(prices)
print(keys[0]) # will print "banana"

A faster way to get the first element without creating a list would be to call next on the iterator. This doesn't generalize nicely when trying to get the nth element though

>>> next(iter(prices))
'banana'

* CPython had guaranteed insertion order as an implementation detail in 3.6.

Ryan Haining
  • 35,360
  • 15
  • 114
  • 174
  • Thanks for the advice. I am sorry for not being more clear. I am just trying to find the code that will let me print out "Banana" NOT the value associated with it. Thanks for all the input! – slagoy May 21 '15 at 11:48
39

If you just want the first key from a dictionary you should use what many have suggested before

first = next(iter(prices))

However if you want the first and keep the rest as a list you could use the values unpacking operator

first, *rest = prices

The same is applicable on values by replacing prices with prices.values() and for both key and value you can even use unpacking assignment

>>> (product, price), *rest = prices.items()
>>> product
'banana'
>>> price
4

Note: You might be tempted to use first, *_ = prices to just get the first key, but I would generally advice against this usage unless the dictionary is very short since it loops over all keys and creating a list for the rest has some overhead.

Note: As mentioned by others insertion order is preserved from python 3.7 (or technically 3.6) and above whereas earlier implementations should be regarded as undefined order.

wihlke
  • 2,455
  • 1
  • 19
  • 18
19

UPDATE: I decided to test it again, now in January of 2023, on my Windows 11 PC, with a Ryzen 9 5900x. So that it's easier for me to re-run it (and so you, dear reader, can run it easily) I've made a Gist of it here: https://gist.github.com/maludwig/d38054ec05d01ad91df5dade8aa47d9d

The results are in, and first_5 remains the winner!

12100238 / s with first_1
 9094216 / s with first_2
 9219988 / s with first_3
 7370554 / s with first_4
13525210 / s with first_5
 9810076 / s with first_6
 8676864 / s with first_7

Everything is a lot faster (CPU is better too, since it's been a few years since the first test). But there have also clearly been optimizations made (see comments for details), especially in first_1.

first_1 is 5.43x faster
first_2 is 4.77x faster
first_3 is 4.62x faster
first_4 is 4.15x faster
first_5 is 3.67x faster
first_6 is 3.47x faster
first_7 is 3.34x faster

Current scoreboard:
  #1: first_5 (previously #1)
  #2: first_1 (previously #4)
  #3: first_6 (previously #2)
  #4: first_3 (previously #5)
  #5: first_2 (previously #6)
  #6: first_7 (previously #3)
  #7: first_4 (previously #7)


So I found this page while trying to optimize a thing for taking the only key in a dictionary of known length 1 and returning only the key. The below process was the fastest for all dictionaries I tried up to size 700.

I tried 7 different approaches, and found that this one was the best, on my 2014 Macbook with Python 3.6:

def first_5():
    for key in biased_dict:
        return key

The results of profiling them were:

  2226460 / s with first_1
  1905620 / s with first_2
  1994654 / s with first_3
  1777946 / s with first_4
  3681252 / s with first_5
  2829067 / s with first_6
  2600622 / s with first_7

All the approaches I tried are here:

def first_1():
    return next(iter(biased_dict))


def first_2():
    return list(biased_dict)[0]


def first_3():
    return next(iter(biased_dict.keys()))


def first_4():
    return list(biased_dict.keys())[0]


def first_5():
    for key in biased_dict:
        return key


def first_6():
    for key in biased_dict.keys():
        return key


def first_7():
    for key, v in biased_dict.items():
        return key
turiyag
  • 2,757
  • 2
  • 22
  • 21
  • 1
    So doing a for loop and return the first key (first_5) is actually the fastest as I can see? Also a nice comparison of the different approaches. – PiMathCLanguage Aug 28 '19 at 08:41
  • 2
    yep, and not just the fastest, but the fastest by a country mile. Also the easiest to read, conveniently. – turiyag Sep 15 '19 at 06:40
  • you're talking about less than a half-microsecond difference between the fastest and slowest method. Unless your code is spending 10%+ more of its time on just getting the first element of a dictionary, this is a weird thing to try to optimize. – Boris Verkhovskiy Jul 15 '21 at 01:59
  • This was a weird thing to optimize. I ended up completely eliminating the dict in the final implementation. Sometimes, it's fun to just get carried away. – turiyag Mar 17 '22 at 20:48
  • A note: The gap between the winner and the losers has narrowed a bit since 3.6 (thanks to the per-opcode `LOAD_GLOBAL` cache and the vectorcall protocol speeding up the `next(iter(biased_dict))` a lot, along with similar optimizations that speed up method calls a bit). In my 3.10.8 install on Alpine on WSLv2, `first_5` still wins over `first_1`, but it's by a factor of 1.45x, not 1.65x as in the OP's tests. I don't really consider it necessarily easier to read (`next(iter(thedict))` is very explicit), but it's a reasonable solution. You could use it outside a function with `for k in d: break`. – ShadowRanger Dec 02 '22 at 00:33
  • I've updated the post with new data and the performance test script link! Very neat! – turiyag Jan 10 '23 at 21:03
13

The dict type is an unordered mapping, so there is no such thing as a "first" element.

What you want is probably collections.OrderedDict.

  • or a namedtuple perhaps if it is immutable – Joran Beasley May 21 '15 at 00:16
  • 14
    This has changed as of Python 3.6. Dictionaries are now ordered. – misantroop Aug 26 '18 at 14:08
  • 1
    Well technically, you want the first element of the dictionary keys if you are certain, there is only one key. – DBX12 Nov 20 '18 at 06:21
  • one could say the first item while iterating over a dict which ifs fixed. But good luck figuring that one out. – demongolem Mar 06 '20 at 14:20
  • @DBX12: If you know it only has one element, [there are better solutions](https://stackoverflow.com/a/33161467/364696) (they work on any iterable, not just `list`s), ones that even verify the assumption that there is one, and only one, element, for free. – ShadowRanger Dec 02 '22 at 00:34
9

Well as simple, the answer according to me will be

first = list(prices)[0]

converting the dictionary to list will output the keys and we will select the first key from the list.

narwanimonish
  • 1,552
  • 17
  • 13
  • 5
    For python3, there's no need to create a whole new list to retrieve only its first element. Better use `next(iter(prices))`, as already suggested by other answers. – normanius Jun 16 '20 at 17:53
  • 1
    @normanius that solution would raise an error on an empty dictionary though... it really depends on the use case, I think creating a list could be useful in some cases (if you know the dictionary will be small and it may be empty for example) – juan Sep 01 '21 at 15:45
  • 1
    @normanius that is indeed the simplest solution, but it is worse than meaningless to someone who doesn't already know this idiom. "next" implies having a position in some sequence. And iter is much less commonly used than [] indexing in codebases I've seen. Furthermore, it requires knowing that when referenced as such, "prices" only returns the keys. It should be prices.keys()[0] or .first or `first(prices.keys())`... that does exactly what it says, but unfortunately Python doesn't understand this. – michael_teter Apr 29 '22 at 13:00
  • @juan: `list(prices)[0]` would also raise an error on an empty dictionary... You *want* an error on an empty dictionary most of the time anyway. If you're in the unusual case where you don't want an error, you can always pass a second argument to `next` (which becomes the value returned when the iterator is empty). – ShadowRanger Dec 02 '22 at 00:36
5

Assuming you want to print the first key:

print(list(prices.keys())[0])

If you want to print first key's value:

print(prices[list(prices.keys())[0]])
Ferd
  • 1,273
  • 14
  • 16
3

As many others have pointed out there is no first value in a dictionary. The sorting in them is arbitrary and you can't count on the sorting being the same every time you access the dictionary. However if you wanted to print the keys there a couple of ways to it:

for key, value in prices.items():
    print(key)

This method uses tuple assignment to access the key and the value. This handy if you need to access both the key and the value for some reason.

for key in prices.keys():
    print(key)

This will only gives access to the keys as the keys() method implies.

kylieCatt
  • 10,672
  • 5
  • 43
  • 51
1

Use a for loop that ranges through all keys in prices:

for key, value in prices.items():
     print(key)
     print("price: %s" % value)

Make sure that you change prices.items() to prices.iteritems() if you're using Python 2.x

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
Mark M
  • 11
  • 3
0

d.keys()[0] to get the individual key.

Update:- @AlejoBernardin , am not sure why you said it didn't work. here I checked and it worked. import collections

prices  = collections.OrderedDict((

    ("banana", 4),
    ("apple", 2),
    ("orange", 1.5),
    ("pear", 3),
))
prices.keys()[0]

'banana'

  • Going by the number of votes, why is this not the best good solution? – GuSuku Jan 26 '18 at 19:57
  • 20
    This works in python2 but not python3. In python3, `dict.keys()` returns a `'dict_keys' object` instead of a `list`, which does not support indexing. – mavix Mar 02 '18 at 23:48
  • TypeError: 'dict_keys' object does not support indexing – anilbey Aug 09 '18 at 20:11
0

Python version >= 3.7 # where dictionaries are ordered

prices = {
    "banana" : 4,
    "apple" : 2,
    "orange" : 1.5,
    "pear" : 3
}

# you can create a list of keys using list(prices.keys())

prices_keys_list = list(prices.keys())

# now you can access the first key of this list 

print(prices_keys_list[0])   # remember 0 is the first index

# you can also do the same for values using list(prices.values())

prices_values_list = list(prices.values())

print(prices_values_list[0])
Talha Sengul
  • 61
  • 1
  • 8