Python-从字典返回前N个key:value对

问题:Python-从字典返回前N个key:value对

考虑以下字典d:

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

我想从d返回前N个key:value对(在这种情况下,N <= 4)。最有效的方法是什么?

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?


回答 0

不需要“前n个”键,因为a dict不会记住首先插入的键。

你可以任意 n键-值对,但:

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

这使用take来自itertools配方的实现:

from itertools import islice

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

看到它在线上工作:ideone


Python 3.6更新

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

There’s no such thing a the “first n” keys because a dict doesn’t remember which keys were inserted first.

You can get any n key-value pairs though:

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

This uses the implementation of take from the itertools recipes:

from itertools import islice

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

See it working online: ideone


Update for Python 3.6

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

回答 1

检索任何内容的一种非常有效的方法是将列表或字典理解与切片结合在一起。如果您不需要订购商品(您只需要n个随机对),则可以使用如下的字典理解:

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

通常,这样的理解总是比等效的“ for y中的x”循环要快。另外,通过使用.keys()创建字典关键字列表并对该列表进行切片,可以避免在构建新字典时“触摸”任何不必要的关键字。

如果不需要键(仅值),则可以使用列表推导:

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

如果您需要根据其键对值进行排序,那么麻烦就不多了:

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

或者,如果您还需要按键:

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

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]}

回答 2

Python的dict不排序,因此要求“前N个”键毫无意义。

collections.OrderedDict如果您需要,可以使用该类。您可以有效地获得其前四个要素

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允许您懒惰地从任何迭代器中获取元素的一部分。如果您希望结果可重用,则需要将其转换为列表或类似内容,例如:

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

Python’s dicts are not ordered, so it’s meaningless to ask for the “first N” keys.

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

回答 3

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

基本上,将视图(dict_items)变成一个迭代器,然后使用next()对其进行迭代。

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().


回答 4

在这里没有看到它。如果只需要从字典中提取某些元素,则不会在语法上排序,而是从语法上最简单。

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

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 d.items()[0:n]}

回答 5

要从python字典中获取前N个元素,可以使用以下代码行:

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

您可以将其更改为:

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

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]

回答 6

参见PEP 0265有关对字典进行排序。然后使用前面提到的可迭代代码。

如果您需要更高效率的已排序键值对。使用不同的数据结构。也就是说,它保持排序顺序和键值关联。

例如

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

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

回答 7

在py3中,这可以解决问题

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

{‘a’:3,’b’:2,’c’:3,’d’:4}

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}


回答 8

只需使用zip添加答案,

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

just add an answer using zip,

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

回答 9

这取决于您的情况下“最有效”的方法。

如果您只想要一个巨大词典的半随机样本foofoo.iteritems()并根据需要使用它并从中获取尽可能多的值,那么这是一个懒惰的操作,可以避免创建键或项的显式列表。

如果您需要先对键进行排序,则无法使用keys = foo.keys(); keys.sort()sorted(foo.iterkeys())来构建键的显式列表。然后对第一个N进行切片或迭代keys

顺便说一句,您为什么关心“有效”方式?您是否对程序进行了简介?如果您没有这样做,请首先使用明显易于理解的方法。它很有可能在不成为瓶颈的情况下做得很好。

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.


回答 10

您可以通过多种方法来实现。如果订单很重要,则可以执行以下操作:

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

如果不需要订购,可以执行以下操作:

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

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

回答 11

字典没有顺序,因此在选择前N个键值对之前,先对其进行排序。

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

现在,我们可以使用以下方法结构来检索前N个元素:

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

要获得前2个元素,则只需使用以下结构:

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)

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)

回答 12

对于Python 3及更高版本,要选择前n对

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

For Python 3 and above,To select first n Pairs

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

回答 13

考虑一个命令

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

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

islice可以解决问题:)希望能有所帮助!

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 !


回答 14

这可能不是很优雅,但是对我有用:

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

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

回答 15

我已经尝试了上面的一些答案,并注意到其中一些是依赖于版本的,并且在3.7版中不起作用。

我还注意到,自3.6起,所有字典均按插入项的顺序排序。

尽管从3.6版开始就对字典进行了排序,但是您希望使用有序结构的某些语句似乎不起作用。

最适合我的OP问题的答案。

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

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