32

Before posting, I have already gone through Access an arbitrary element in a dictionary in Python, butI'm uncertain about this.

I have a long dictionary and I've to get the values of its first and last keys. I can use dict[dict.keys()[0]] and dict[dict.keys()[-1]] to get the first and last elements, but since the key:value pairs are outputted in a random form(as in the positioning of the key:value pairs is random), will the solution provided in this link always work?

martineau
  • 112,593
  • 23
  • 157
  • 280
PythonEnthusiast
  • 15,691
  • 41
  • 122
  • 238

8 Answers8

33

Use an OrderedDict, because a normal dictionary doesn't preserve the insertion order of its elements when traversing it. Here's how:

# import the right class
from collections import OrderedDict

# create and fill the dictionary
d = OrderedDict()
d['first']  = 1
d['second'] = 2
d['third']  = 3

# retrieve key/value pairs
els = list(d.items()) # explicitly convert to a list, in case it's Python 3.x

# get first inserted element 
els[0]
=> ('first', 1)

# get last inserted element 
els[-1]
=> ('third', 3)
Óscar López
  • 225,348
  • 35
  • 301
  • 374
  • 15
    As of Python 3.6 OrderDict() is no longer necessary, because the current native dictionary implementation preserves insertion order. – juan Isaza Jun 01 '17 at 23:38
  • @juanIsaza Can you provide a proof link please?! – AmirHossein Jul 30 '17 at 10:48
  • Is there a way of doing it without having to copy the entire dictionary content to a list? Something like d.front() and d.back() ? – Mattia Sep 27 '17 at 14:51
  • 1
    @TechJS I updated his answer with a link to the documentation and some quotes for proof. – NOhs Jan 21 '19 at 12:49
16

If working with Python 3.6+ you can do a one liner:

First:

list({'fist': 1, 'second': 2, 'last': 3}.items())[0]
=> ('first', 1)

Last:

list({'fist': 1, 'second': 2, 'third': 3}.items())[-1]
=> ('third', 1)

This is the case because Python 3.6+ default dictionary preserves insertion order. This is also mentioned in the documentation:

Dictionaries preserve insertion order. Note that updating a key does not affect the order. Keys added after deletion are inserted at the end.

and

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

NOhs
  • 2,730
  • 3
  • 22
  • 53
juan Isaza
  • 3,123
  • 2
  • 28
  • 36
  • 1
    Not necessarily safe to rely on standard dicts being ordered: http://gandenberger.org/2018/03/10/ordered-dicts-vs-ordereddict/ – fantabolous Nov 20 '18 at 06:12
  • 1
    @fantabolous Off course Pandas and other libraries who predate Python3.6 won't assume any order, but still the language is evolving and you should embrace new ways of doing things or you get stuck in the past and in the end you loose productivity. – juan Isaza Feb 03 '21 at 11:45
2

Python dictionaries are unordered, so "first" and "last" isn't defined. Instead, you can sort your keys, and then access the element associated with the first and last key in your sorted set.

EDIT:

The OP clarified that by "first" and "last" he meant the order in which keys were added to the dictionary. collections.OrderedDict should work for this case.

Codie CodeMonkey
  • 7,339
  • 2
  • 27
  • 43
  • Thats what I said. Is there any solution for this? – PythonEnthusiast Sep 26 '13 at 13:54
  • @user1162512 I've added a suggestion for sorting the keys, but that's the best you can do. – Codie CodeMonkey Sep 26 '13 at 13:56
  • What if I store my dictionary as `dict= {"xyz":294,"a":1,"rah":129}`. On what basis would I sort the keys in order to get the access of xyz and rah. – PythonEnthusiast Sep 26 '13 at 13:57
  • PS: I dont want to search using dict["xyz"] – PythonEnthusiast Sep 26 '13 at 13:57
  • 1
    @user1162512: the second you write `{"xyz":294,"a":1,"rah":129}`, you've lost any information about the order, because that's a dictionary literal. As mentioned elsewhere in this thread, you can use `collections.OrderedDict` for an insertion-order variant. – DSM Sep 26 '13 at 13:58
  • @user1162512 As someone else commented, it depends what you meant by first and last. If you mean first inserted (in terms of time), then collections.OrderedDict is the way to go. I had assumed you meant first according to some ordering. – Codie CodeMonkey Sep 26 '13 at 14:01
  • @user1162512 The solution is to use OrderedDict which does keep track of element order and has a perfectly defined first and last element. – user4815162342 Sep 26 '13 at 14:01
1

There is no such thing as "first" or "last" key in dictionary, which does not guarantee any particular ordering. So there is no possibility to get "first" or "last" element. You can only create your own wrapper around python dict, which will store the information about "first" and "last" object

Something like

class MyDict:

  def __init__(self):
    self.first=None
    self.last=None
    self.dict={}

  def add( key, value ):
    if self.first==None: self.first=key
    self.last=key
    self.dict[key]=value

  def get( key ):
    return self.dict[key]

  def first():
    return self.dict[ self.first ]

  def last():
    return self.dict[ self.last ]

Although as it was pointed out in the comment there is already a class OrderedDict: http://docs.python.org/2/library/collections.html#collections.OrderedDict

Ordered dictionaries are just like regular dictionaries but they remember the order that items were inserted. When iterating over an ordered dictionary, the items are returned in the order their keys were first added.

lejlot
  • 61,451
  • 8
  • 126
  • 152
1

With OrderedDict you can use iterators

d = OrderedDict(a=1, b=2, c=3)
next(iter(d)) # returns 'a'
next(reversed(d) # returns 'c'
Volodymyr
  • 11
  • 1
0

You can do it by using list().

dir = dict()

dir['Key-3'] = 'Value-3'    # Added First Item
dir['Key-2'] = 'Value-2'    # Added Second Item
dir['Key-4'] = 'Value-4'    # Added Third Item
dir['Key-1'] = 'Value-1'    # Added Fourth Item

lst = list(dir.items())     # For key & value
# lst = list(dir.keys())    # For keys
# lst = list(dir.values())  # For values

print('First Element:- ', lst[0])
print('Last Element:- ', lst[-1])

Output:-

First Element:- ('Key-3', 'Value-3')

Last Element:- ('Key-1', 'Value-1')

Niraj Phutane
  • 978
  • 7
  • 8
0

Obviously it's too late to answer, yet I'd like to add the following to the awesome answers above

dct = {"first": 1, "second": 2, "last": 3}

first, *_, last = dct.items()
print("*** Items ***")
print("First Item:", first)
print("Last Item:", last)

first, *_, last = dct.keys()
print("*** Keys ***")
print("First Key:", first)
print("Last Key:", last)

first, *_, last = dct.values()
print("*** Values ***")
print("First Value:", first)
print("Last Value:", last)
*** Items ***
First Item: ('first', 1)
Last Item: ('last', 3)

*** Keys ***
First Key: first
Last Key: last

*** Values ***
First Value: 1
Last Value: 3
Tes3awy
  • 2,094
  • 4
  • 24
  • 47
-1

def dictionarySortingExample(yourDictionary):

#get all the keys and store them to a list
allKeys = yourDictionary.keys()

#sort the list of keys
allKeysSorted = sorted(allKeys)

#retrieve the first and last keys in the list
firstKey = allKeysSorted[0]
lastKey = allKeysSorted[-1]

#retrive the values from the dictionary
firstValue = yourDictionary[firstKey]
lastValue = yourDictionary[lastKey]

print "---Sorted Dictionary---"
print "original dictionary: " + str(yourDictionary)
print "list of all keys: " + str(allKeys)
print "ordered list of all keys: " + str(allKeysSorted)
print "first item in sorted dictionary: " + str(firstKey) + ":" + str(firstValue)
print "last item in sorted dictionary: " + str(lastKey) + ":" + str(lastValue)

example dictionary sorting

sampleDictionary = {4:"four", "Cranberry":2, 3:"three", 2:"two", "Apple":3, 1:"one", "Bananna":1} dictionarySortingExample(sampleDictionary)