Skip to content

How to Work with collections.OrderedDict (Get First/Last, Indexing, Merging) in Python

Learn how to access first/last elements, index items, merge dictionaries, and convert OrderedDict objects in Python while maintaining insertion order.

While standard Python dictionaries (dict) preserve insertion order as of Python 3.7+, the collections.OrderedDict class was the primary way to guarantee order in earlier Python versions and still offers some specific behaviors (like equality comparison considering order). Working with ordered dictionaries sometimes requires accessing elements based on their insertion position (like the first or last item) or finding the numerical index of a key.

This guide demonstrates common operations on OrderedDict objects, including getting the first/last elements, accessing items by index, merging, finding indices, and converting to standard types.

Understanding OrderedDict (and dict Order)

collections.OrderedDict is a dictionary subclass that remembers the order in which keys were first inserted. If a new entry overwrites an existing entry, the original insertion position is left unchanged. Deleting and reinserting an entry moves it to the end.

from collections import OrderedDict

od = OrderedDict()
od['apple'] = 1
od['banana'] = 2
od['cherry'] = 3

print(f"Initial OrderedDict: {od}")

Getting the First Element (Key, Value, Item)

Since OrderedDict maintains insertion order, you can reliably get the first added item.

Using next() and iter()

The most direct way is to get an iterator from the dictionary (which yields keys by default) or its views (.values(), .items()) and fetch the first item using next().

from collections import OrderedDict

my_od = OrderedDict(
    [('first', 'Apple'), ('second', 'Banana'), ('third', 'Cherry')]
)

if my_od: # Check if not empty before using next() without default
    first_key = next(iter(my_od))
    print(f"First Key: '{first_key}'")                   # Output: First Key: 'first'

    first_value = my_od[first_key]
    print(f"First Value: '{first_value}'")               # Output: First Value: 'Apple'

    first_item_pair = next(iter(my_od.items()))
    print(f"First Item (Key, Value): {first_item_pair}") # Output: First Item (Key, Value): ('first', 'Apple')
else:
    print("OrderedDict is empty.")

Output:

First Key: 'first'
First Value: 'Apple'
First Item (Key, Value): ('first', 'Apple')
  • iter(my_od): Creates an iterator over the keys of the OrderedDict in insertion order.
  • iter(my_od.items()): Creates an iterator over the (key, value) pairs in insertion order.
  • next(iterator): Retrieves the next (in this case, the first) item from the iterator.

Handling Empty Dictionaries

Calling next() on an iterator obtained from an empty OrderedDict will raise a StopIteration error. To handle this gracefully, provide a default value to next().

from collections import OrderedDict

empty_od = OrderedDict()

first_key = next(iter(empty_od), None)
first_item = next(iter(empty_od.items()), None)

print(f"First key (empty): {first_key}")   # Output: First key (empty): None
print(f"First item (empty): {first_item}") # Output: First item (empty): None

Getting the Last Element (Key, Value, Item)

Using next() and reversed()

Combine reversed() with next() to get the last inserted item efficiently.

from collections import OrderedDict

my_od = OrderedDict(
    [('first', 'Apple'), ('second', 'Banana'), ('third', 'Cherry')]
)

if my_od:
    last_key = next(reversed(my_od))
    print(f"Last Key: '{last_key}'")                    # Output: Last Key: 'third'

    last_value = my_od[last_key]
    print(f"Last Value: '{last_value}'")                # Output: Last Value: 'Cherry'

    last_item_pair = next(reversed(my_od.items()))
    print(f"Last Item (Key, Value): {last_item_pair}")  # Output: Last Item (Key, Value): ('third', 'Cherry')
else:
    print("OrderedDict is empty.")

Output:

Last Key: 'third'
Last Value: 'Cherry'
Last Item (Key, Value): ('third', 'Cherry')
  • reversed(my_od): Creates a reverse iterator over the keys.
  • reversed(my_od.items()): Creates a reverse iterator over the items.
  • next(...): Gets the first item from the reversed iterator, which corresponds to the last item in the original OrderedDict.

Handling Empty Dictionaries

Use the default argument with next() for empty dictionaries, just like when getting the first element.

from collections import OrderedDict

empty_od = OrderedDict()

last_key = next(reversed(empty_od), None)
last_item = next(reversed(empty_od.items()), None)

print(f"Last key (empty): {last_key}")   # Output: Last key (empty): None
print(f"Last item (empty): {last_item}") # Output: Last item (empty): None

Output:

Last key (empty): None
Last item (empty): None

Accessing Items by Index (Positional Access)

OrderedDict objects themselves are not directly subscriptable by integer index (like my_od[0]). To access the Nth item based on insertion order, you must first convert a view (.keys(), .values(), or .items()) into a list.

Converting to List First

from collections import OrderedDict

my_od = OrderedDict(
    [('apple', 1), ('banana', 2), ('cherry', 3), ('date', 4)]
)

items_list = list(my_od.items())
print(f"Items as list: {items_list}")

try:
    second_item = items_list[1] # Index 1 corresponds to the second item inserted
    print(f"Second item (index 1): {second_item}")          # Output: Second item (index 1): ('banana', 2)

    second_key = second_item[0]
    second_value = second_item[1]
    print(f"  Key: {second_key}, Value: {second_value}")    # Output: Key: banana, Value: 2

    last_item = items_list[-1]
    print(f"Last item (index -1): {last_item}")             # Output: Last item (index -1): ('date', 4)

except IndexError:
    print("Index out of range for the items list.")

Output:

Items as list: [('apple', 1), ('banana', 2), ('cherry', 3), ('date', 4)]
Second item (index 1): ('banana', 2)
  Key: banana, Value: 2
Last item (index -1): ('date', 4)
  • list(my_od.items()): Creates a list of (key, value) tuples in insertion order.
  • You can then use standard list indexing ([index]) on this list.

Accessing Keys/Values by Index

Similarly, convert .keys() or .values() to a list first.

from collections import OrderedDict

my_od = OrderedDict(
    [('apple', 1), ('banana', 2), ('cherry', 3), ('date', 4)]
)

keys_list = list(my_od.keys())
print(f"Keys list: {keys_list}")                    # Output: Keys list: ['apple', 'banana', 'cherry', 'date']
print(f"Third key (index 2): '{keys_list[2]}'")     # Output: Third key (index 2): 'cherry'

values_list = list(my_od.values())
print(f"Values list: {values_list}")                # Output: Values list: [1, 2, 3, 4]
print(f"First value (index 0): {values_list[0]}")   # Output: First value (index 0): 1

Output:

Keys list: ['apple', 'banana', 'cherry', 'date']
Third key (index 2): 'cherry'
Values list: [1, 2, 3, 4]
First value (index 0): 1

Getting All Keys/Values/Items as a List

As shown above, simply use list() on the corresponding view object:

  • list(my_od.keys())
  • list(my_od.values())
  • list(my_od.items())

Getting the Index of a Key or Value

To find the numerical index (based on insertion order) of a known key or value:

Finding Index of a Key

Convert keys to a list and use list.index().

from collections import OrderedDict

my_od = OrderedDict(
    [('apple', 1), ('banana', 2), ('cherry', 3)]
)

keys_list = list(my_od.keys()) # ['apple', 'banana', 'cherry']

try:
    index_of_cherry = keys_list.index('cherry')
    print(f"Index of key 'cherry': {index_of_cherry}") # Output: Index of key 'cherry': 2
except ValueError:
    print("Key not found.")

Finding Index of a Value

Convert values to a list and use list.index(). Note this finds the index of the first occurrence if the value is duplicated.

from collections import OrderedDict

my_od = OrderedDict(
    [('apple', 10), ('banana', 20), ('cherry', 30), ('date', 20)]
)

values_list = list(my_od.values()) # [10, 20, 30, 20]

try:
    index_of_20 = values_list.index(20)
    print(f"Index of first value 20: {index_of_20}") # Output: Index of first value 20: 1
except ValueError:
    print("Value not found.")
  • list.index() raises a ValueError if the item is not found. Use try...except or an if value in values_list: check first.

Merging Two OrderedDict Objects

Creating a New Merged OrderedDict

Concatenate the .items() lists from both dictionaries and pass the result to the OrderedDict constructor. This preserves the order from the first dict, followed by the order from the second. Keys from the second dict will overwrite keys from the first if they conflict.

from collections import OrderedDict

od1 = OrderedDict([('a', 1), ('b', 2)])
od2 = OrderedDict([('b', 20), ('c', 3), ('d', 4)]) # 'b' will overwrite

merged_items = list(od1.items()) + list(od2.items())
merged_od = OrderedDict(merged_items)

print(f"OD1: {od1}")                # Output: OD1: OrderedDict({'a': 1, 'b': 2})
print(f"OD2: {od2}")                # Output: OD2: OrderedDict({'b': 20, 'c': 3, 'd': 4})
print(f"Merged OD: {merged_od}")    # Output: Merged OD: OrderedDict({'a': 1, 'b': 20, 'c': 3, 'd': 4})

Updating an OrderedDict In-Place

Use the standard update() method. This modifies the first OrderedDict directly. New keys from the second dict are appended to the end. Existing keys are updated in place, retaining their original position.

from collections import OrderedDict

od1 = OrderedDict([('a', 1), ('b', 2), ('e', 5)])
od2 = OrderedDict([('c', 3), ('b', 20), ('d', 4)]) # 'b' exists, 'c','d' are new

print(f"OD1 before update: {od1}")

od1.update(od2)

print(f"OD1 after update: {od1}")

Converting OrderedDict to dict or list

  • To dict: Simply pass the OrderedDict to the dict() constructor. The order is preserved if using Python 3.7+.
    from collections import OrderedDict
    my_od = OrderedDict([('b', 2), ('a', 1)])
    regular_dict = dict(my_od)
    print(f"Converted to dict: {regular_dict}") # Output: {'b': 2, 'a': 1}
    print(f"Type: {type(regular_dict)}")        # Output: <class 'dict'>
  • To list: Convert the desired view (.keys(), .values(), .items()) using list().
    from collections import OrderedDict
    my_od = OrderedDict([('b', 2), ('a', 1)])
    items_list = list(my_od.items())
    print(f"Converted to list of items: {items_list}") # Output: [('b', 2), ('a', 1)]

Conclusion

While standard Python dictionaries now preserve insertion order (since 3.7), collections.OrderedDict offers explicit order guarantees and compatibility. Key operations include:

  • Getting the first/last elements using next(iter(od)) or next(reversed(od)).
  • Accessing by index requires converting .keys(), .values(), or .items() to a list first.
  • Finding the index of a key/value also requires converting the appropriate view to a list and using list.index().
  • Merging can be done by concatenating .items() lists into a new OrderedDict or using .update() to modify in-place.
  • Converting to dict or list is straightforward using the respective constructors.

Remember the standard dict capabilities in modern Python, but use OrderedDict when explicit order or pre-3.7 compatibility is required.

Navigation