37

Before posting, I have already gone through Access an arbitrary element in a dictionary in Python, but I'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?

user4035
  • 22,508
  • 11
  • 59
  • 94
Praful Bagai
  • 16,684
  • 50
  • 136
  • 267
  • If d is a dict, In Python 3, d.keys() is an iterable rather than a list, so dict.keys()[-1] doesn't work. In Python 3.7+, next(reversed(d.keys())) does work, but more important, next(reversed(d.values())) gets you the last-added value in constant time. – SteveWithamDuplicate Sep 02 '22 at 16:36

8 Answers8

36

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
  • 232,561
  • 37
  • 312
  • 386
21

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,780
  • 3
  • 25
  • 59
juan Isaza
  • 3,646
  • 3
  • 31
  • 37
  • 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
  • 2
    @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
5

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
  • 51
  • 1
  • 1
  • 3
    This works with a regular dict in Python 3.7+. As far as I can see, this is the only CONSTANT-TIME way to get the last element of a dict (in Python 3.7+) or DefaultDict before that. The use of "reversed" may make people worry it constructs a list, or worse, sorts-- it doesn't. – SteveWithamDuplicate Sep 02 '22 at 16:55
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,669
  • 2
  • 29
  • 45
  • Thats what I said. Is there any solution for this? – Praful Bagai 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. – Praful Bagai Sep 26 '13 at 13:57
  • PS: I dont want to search using dict["xyz"] – Praful Bagai 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

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')

NirajPhutane
  • 1,586
  • 1
  • 12
  • 10
  • Mind, only starting from python version 3.7 dictionary order is guaranteed to be equal to insertion order. – parvus Jun 16 '22 at 12:21
1

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,166
  • 5
  • 29
  • 51
  • 1
    This is so much easier than converting the dictionary to a list. – howdoicode Jul 28 '22 at 18:48
  • @Tes3awy, that does convert all but the first and last elements to the list _ (underscore by itself is a Python variable name). I've confirmed this with a longer dictionary in Python 3.10 – SteveWithamDuplicate Sep 02 '22 at 16:42
  • @SteveWithamDuplicate Yes, it does convert the elements in between the first and the last. – Tes3awy Sep 03 '22 at 17:54
  • @SteveWithamDuplicate But what is the problem here? – Tes3awy Sep 03 '22 at 18:35
  • Hi, @Tes3awy, it's just that howdoicode said it's "easier than converting the dictionary to a list." And since it *is* converting the dictionary to a list, that means two things: 1) That's how easy it is to convert a dictionary to a list in Python, and 2) If the dictionary is large, this would be a costly way to get one element out of it. So, since howdoicode didn't understand that, it could cause a problem in practice for them. Especially because one *can* get the first and last items *without* converting to a list. – SteveWithamDuplicate Sep 06 '22 at 00:55
0

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
  • 64,777
  • 8
  • 131
  • 164
-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)