78

What's the shortest way to get first item of OrderedDict in Python 3?

My best:

list(ordered_dict.items())[0]

Quite long and ugly.

I can think of:

next(iter(ordered_dict.items()))       # Fixed, thanks Ashwini

But it's not very self-describing.

Any better suggestions?

jpp
  • 159,742
  • 34
  • 281
  • 339
Ram Rachum
  • 84,019
  • 84
  • 236
  • 374
  • 3
    using list is a bad idea. the entire list will be populate before you'll get the first item. Using next() is optimal because .items() return an iterator and will yield only one value. – gawel Jan 11 '14 at 13:31
  • What do you mean by shortest way? lesser number of characters? – thefourtheye Jan 11 '14 at 13:32
  • 2
    I think you'll need an `iter` call too: `next(iter(d.items()))` as `.items` returns a View object. – Ashwini Chaudhary Jan 11 '14 at 13:32
  • 1
    @thefourtheye yes, less characters, but hopefully idiomatic too. – Ram Rachum Jan 11 '14 at 14:16
  • I was wondering if `next(iter(ordered_dict.items()))` this will advance the iterator or not. As expected it does not advance the iterator! Also is it safe to assume that `next(iter(ordered_dict.items()))` runs in `O(1)` time? – user 923227 Feb 06 '19 at 20:22
  • `next(iter(self.items()))` will give you the first pair `(key, val)` – Charlie Parker Oct 29 '21 at 23:23

7 Answers7

75

Programming Practices for Readabililty

In general, if you feel like code is not self-describing, the usual solution is to factor it out into a well-named function:

def first(s):
    '''Return the first element from an ordered collection
       or an arbitrary element from an unordered collection.
       Raise StopIteration if the collection is empty.
    '''
    return next(iter(s))

With that helper function, the subsequent code becomes very readable:

>>> extension = {'xml', 'html', 'css', 'php', 'xhmtl'}
>>> one_extension = first(extension)

Patterns for Extracting a Single Value from Collection

The usual ways to get an element from a set, dict, OrderedDict, generator, or other non-indexable collection are:

for value in some_collection:
    break

and:

value = next(iter(some_collection))

The latter is nice because the next() function lets you specify a default value if collection is empty or you can choose to let it raise an exception. The next() function is also explicit that it is asking for the next item.

Alternative Approach

If you actually need indexing and slicing and other sequence behaviors (such as indexing multiple elements), it is a simple matter to convert to a list with list(some_collection) or to use [itertools.islice()][2]:

s = list(some_collection)
print(s[0], s[1])

s = list(islice(n, some_collection))
print(s)
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
  • I like the latter option, but in your opinion is it better than ```list(ordered_dict.items())[0]```? If anything I think the ```[0]``` is more obvious. – Bede Constantinides Aug 16 '16 at 13:07
  • 1
    @bedeabc `list(ordered_dict.items())[0]` goes ahead to create a _list of all items in the dict_, then takes the first item of that list, then throws away that list. You certainly don't want to do that. – Mr_and_Mrs_D May 24 '17 at 17:38
  • @Mr_and_Mrs_D I understand, and have become comfortable with the next(iter()) pattern, but for trivially small data structures I don't see the issue with prioritising readability. – Bede Constantinides May 24 '17 at 22:23
  • `next(iter(self.items()))` will give you the first pair `(key, val)` – Charlie Parker Oct 29 '21 at 23:23
31

Use popitem(last=False), but keep in mind that it removes the entry from the dictionary, i.e. is destructive.

from collections import OrderedDict
o = OrderedDict()
o['first'] = 123
o['second'] = 234
o['third'] = 345

first_item = o.popitem(last=False)
>>> ('first', 123)

For more details, have a look at the manual on collections. It also works with Python 2.x.

ralien
  • 1,448
  • 11
  • 24
5

Subclassing and adding a method to OrderedDict would be the answer to clarity issues:

>>> o = ExtOrderedDict(('a',1), ('b', 2))
>>> o.first_item()
('a', 1)

The implementation of ExtOrderedDict:

class ExtOrderedDict(OrderedDict):
    def first_item(self):
        return next(iter(self.items()))
Bryce Guinta
  • 3,456
  • 1
  • 35
  • 36
5

Code that's readable, leaves the OrderedDict unchanged and doesn't needlessly generate a potentially large list just to get the first item:

for item in ordered_dict.items():
    return item

If ordered_dict is empty, None would be returned implicitly.

An alternate version for use inside a stretch of code:

for first in ordered_dict.items():
    break  # Leave the name 'first' bound to the first item
else:
    raise IndexError("Empty ordered dict")

The Python 2.x code corresponding to the first example above would need to use iteritems() instead:

for item in ordered_dict.iteritems():
    return item
Isac Casapu
  • 1,163
  • 13
  • 21
1

You might want to consider using SortedDict instead of OrderedDict.

It provides SortedDict.peekitem to peek an item.

Runtime complexity: O(log(n))

>>> sd = SortedDict({'a': 1, 'b': 2, 'c': 3})
>>> sd.peekitem(0)
('a', 1)
Faker
  • 121
  • 4
0

If you need a one-liner:

ordered_dict[[*ordered_dict.keys()][0]]

It creates a list of dict keys, picks the first and use it as key to access the dictionary value.

Frank
  • 1,959
  • 12
  • 27
-2

First record:

[key for key, value in ordered_dict][0]

Last record:

[key for key, value in ordered_dict][-1]
galaga4
  • 19
  • 2
    Hi, thank you for your contribution to StackOverflow! While this works and is straightforward to understand, this is a very inefficient way to do it, as the whole list will have to be created in memory, before the single element you want can be extracted. – Kritzefitz Feb 01 '19 at 19:43
  • Welcome to StackOverflow @galaga4! Can you help me here - Looks like this is will create a List which is not needed! – user 923227 Feb 06 '19 at 19:30
  • The fact that it is inefficient does not make it wrong. It's a perfectly fine solution and may be an easy way to get what OP wants for short lists. – cerebrou Mar 13 '21 at 21:04
  • `next(iter(self.items()))` will give you the first pair `(key, val)` – Charlie Parker Oct 29 '21 at 23:24