Jason Strimpel
Jason Strimpel

Reputation: 15496

Return first N key:value pairs from dict

Consider the following dictionary, d:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

I want to return the first N key:value pairs from d (N <= 4 in this case). What is the most efficient method of doing this?

Upvotes: 212

Views: 367969

Answers (22)

Mark Byers
Mark Byers

Reputation: 838716

Prior to Python 3.6 there is no such thing a the "first n" keys because a dict doesn't remember which keys were inserted first.

You can get first n iteration sorted key-value pairs though:

n_items = take(n, d.items())

This uses the implementation of take from the itertools recipes:

from itertools import islice

def take(n, iterable):
    """Return the first n items of the iterable as a list."""
    return list(islice(iterable, n))

See it working online: ideone

For Python < 3.6

n_items = take(n, d.iteritems())

Upvotes: 172

user2623954
user2623954

Reputation: 1229

Did not see it on here. Will not be ordered but the simplest syntactically if you need to just take some elements from a dictionary.

n = 2
{key:value for key,value in list(d.items())[0:n]}

Upvotes: 7

Python's dicts are not guaranteed to be ordered in Python <= 3.6, so it's meaningless to ask for the "first N" keys in older Python versions.

The collections.OrderedDict class is available if that's what you need. You could efficiently get its first four elements as

import itertools
import collections

d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
x = itertools.islice(d.items(), 0, 4)

for key, value in x:
    print key, value

itertools.islice allows you to lazily take a slice of elements from any iterator. If you want the result to be reusable you'd need to convert it to a list or something, like so:

x = list(itertools.islice(d.items(), 0, 4))

Upvotes: 19

Peyman
Peyman

Reputation: 4209

Unfortunately, most of the answers are not efficient. This is the most efficient way that I know of. Were d is your dictionary and n is the printing number:

for idx, k in enumerate(d):
  if idx == n: break
  print((k, d[k]))

Here idx means index and k means key. Consequently d[k] will be the value.

Casting your dictionary to a list can be slow:

Your dictionary may be too large and you don't need to cast all of it just for printing a few of the first. Both list(d.items()) and list(d.keys()) are slow.

Time Performance Comparison:

Here is the time comparison of the three methods. Random dictionaries were generated from lengths 10 to 1000, and their 5 first elements were printed. As you can see the performance of enumerate(d) is O(1) and won't be changed by the length of the dictionary. This is not true for list(d.items()) and list(d.keys()) which are O(n). enter image description here

Upvotes: 14

PRS
PRS

Reputation: 51

This will work for python 3.8+:

d_new = {k:v for i, (k, v) in enumerate(d.items()) if i < n}

Upvotes: 5

MichaelJanz
MichaelJanz

Reputation: 1815

I like this one because no new list needs to be created, its a one liner which does exactly what you want and it works with python >= 3.8 (where dictionaries are indeed ordered, I think from python 3.6 on?):

new_d = {kv[0]:kv[1] for i, kv in enumerate(d.items()) if i <= 4}

Upvotes: 1

user566245
user566245

Reputation: 4227

You can get dictionary items by calling .items() on the dictionary. then convert that to a list and from there get first N items as you would on any list.

below code prints first 3 items of the dictionary object

e.g.

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

first_three_items = list(d.items())[:3]

print(first_three_items)

Outputs:

[('a', 3), ('b', 2), ('c', 3)]

Upvotes: 16

Avio
Avio

Reputation: 2717

For Python 3.8 the correct answer should be:

import more_itertools

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

first_n = more_itertools.take(3, d.items())
print(len(first_n))
print(first_n)

Whose output is:

3
[('a', 3), ('b', 2), ('c', 3)]

After pip install more-itertools of course.

Upvotes: 8

Shashwata Shastri
Shashwata Shastri

Reputation: 13

def GetNFirstItems(self):
    self.dict = {f'Item{i + 1}': round(uniform(20.40, 50.50), 2) for i in range(10)}#Example Dict
    self.get_items = int(input())
    for self.index,self.item in zip(range(len(self.dict)),self.dict.items()):
        if self.index==self.get_items:
          break
        else:
            print(self.item,",",end="")

Unusual approach, as it gives out intense O(N) time complexity.

Upvotes: 0

Farid Khafizov
Farid Khafizov

Reputation: 1200

in py3, this will do the trick

{A:N for (A,N) in [x for x in d.items()][:4]}

{'a': 3, 'b': 2, 'c': 3, 'd': 4}

Upvotes: 11

Mark Kortink
Mark Kortink

Reputation: 2120

I have tried a few of the answers above and note that some of them are version dependent and do not work in version 3.7.

I also note that since 3.6 all dictionaries are ordered by the sequence in which items are inserted.

Despite dictionaries being ordered since 3.6 some of the statements you expect to work with ordered structures don't seem to work.

The answer to the OP question that worked best for me.

itr = iter(dic.items())
lst = [next(itr) for i in range(3)]

Upvotes: 0

thevatsalsaglani
thevatsalsaglani

Reputation: 603

To get the top N elements from your python dictionary one can use the following line of code:

list(dictionaryName.items())[:N]

In your case you can change it to:

list(d.items())[:4]

Upvotes: 59

Thorsten Stehlik
Thorsten Stehlik

Reputation: 11

This might not be very elegant, but works for me:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

x= 0
for key, val in d.items():
    if x == 2:
        break
    else:
        x += 1
        # Do something with the first two key-value pairs

Upvotes: 1

Peter Li
Peter Li

Reputation: 789

just add an answer using zip,

{k: d[k] for k, _ in zip(d, range(n))}

Upvotes: 2

Wickkiey
Wickkiey

Reputation: 4642

consider a dict

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

from itertools import islice
n = 3
list(islice(d.items(),n))

islice will do the trick :) hope it helps !

Upvotes: 0

monotasker
monotasker

Reputation: 2112

A very efficient way to retrieve anything is to combine list or dictionary comprehensions with slicing. If you don't need to order the items (you just want n random pairs), you can use a dictionary comprehension like this:

# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}

Generally a comprehension like this is always faster to run than the equivalent "for x in y" loop. Also, by using .keys() to make a list of the dictionary keys and slicing that list you avoid 'touching' any unnecessary keys when you build the new dictionary.

If you don't need the keys (only the values) you can use a list comprehension:

first2vals = [v for v in mydict.values()[:2]]

If you need the values sorted based on their keys, it's not much more trouble:

first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]

or if you need the keys as well:

first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}

Upvotes: 148

Shivpe_R
Shivpe_R

Reputation: 1080

For Python 3 and above,To select first n Pairs

n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}

Upvotes: 1

cop4587
cop4587

Reputation: 151

foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
iterator = iter(foo.items())
for i in range(3):
    print(next(iterator))

Basically, turn the view (dict_items) into an iterator, and then iterate it with next().

Upvotes: 15

Jyothish Arumugam
Jyothish Arumugam

Reputation: 25

Dictionary maintains no order , so before picking top N key value pairs lets make it sorted.

import operator
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
#itemgetter(0)=sort by keys, itemgetter(1)=sort by values

Now we can do the retrieval of top 'N' elements:, using the method structure like this:

def return_top(elements,dictionary_element):
    '''Takes the dictionary and the 'N' elements needed in return
    '''
    topers={}
    for h,i in enumerate(dictionary_element):
        if h<elements:
            topers.update({i:dictionary_element[i]})
    return topers

to get the top 2 elements then simply use this structure:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
d=return_top(2,d)
print(d)

Upvotes: 0

silverjam
silverjam

Reputation: 400

See PEP 0265 on sorting dictionaries. Then use the aforementioned iterable code.

If you need more efficiency in the sorted key-value pairs. Use a different data structure. That is, one that maintains sorted order and the key-value associations.

E.g.

import bisect

kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
bisect.insort_left(kvlist, ('d', 4))

print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

Upvotes: 3

9000
9000

Reputation: 40894

This depends on what is 'most efficient' in your case.

If you just want a semi-random sample of a huge dictionary foo, use foo.iteritems() and take as many values from it as you need, it's a lazy operation that avoids creation of an explicit list of keys or items.

If you need to sort keys first, there's no way around using something like keys = foo.keys(); keys.sort() or sorted(foo.iterkeys()), you'll have to build an explicit list of keys. Then slice or iterate through first N keys.

BTW why do you care about the 'efficient' way? Did you profile your program? If you did not, use the obvious and easy to understand way first. Chances are it will do pretty well without becoming a bottleneck.

Upvotes: 1

g.d.d.c
g.d.d.c

Reputation: 48028

You can approach this a number of ways. If order is important you can do this:

for key in sorted(d.keys()):
  item = d.pop(key)

If order isn't a concern you can do this:

for i in range(4):
  item = d.popitem()

Upvotes: 0

Related Questions