繁体   English   中英

从 dict 返回前 N 个键:值对

[英]Return first N key:value pairs from dict

考虑以下字典 d:

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

我想从 d 返回前 N 个键:值对(在本例中为 N <= 4)。 这样做最有效的方法是什么?

没有“前 n”键这样的东西,因为dict不记得首先插入了哪些键。

你可以得到任何n 个键值对:

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

这使用了itertools食谱中take实现:

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

检索任何内容的一种非常有效的方法是将列表或字典推导式与切片相结合。 如果您不需要订购项目(您只需要 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 x in y”循环运行得更快。 此外,通过使用 .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]}

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

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

在您的情况下,您可以将其更改为:

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

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))
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() 对其进行迭代。

在 py3 中,这可以解决问题

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

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

对于Python 3.8 ,正确答案应该是:

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)

谁的输出是:

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

当然在pip install more-itertools之后。

没看到这里。 如果您只需要从字典中获取一些元素,则不会排序,但在语法上是最简单的。

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

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

只需使用 zip 添加答案,

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

对于 Python 3 及以上,选择前 n 对

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

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

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

这取决于在您的情况下什么是“最有效”的。

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

如果您需要先对键进行排序,则无法使用诸如keys = foo.keys(); keys.sort() keys = foo.keys(); keys.sort()sorted(foo.iterkeys()) ,你必须建立一个明确的键列表。 然后切片或迭代前 N 个keys

顺便说一句,你为什么关心“高效”的方式? 您是否对您的程序进行了概要分析? 如果没有,请先使用明显易于理解的方式。 有可能它会做得很好而不会成为瓶颈。

字典不维护顺序,因此在选择前 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)

考虑一个字典

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

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

islice 会解决问题:) 希望它有所帮助!

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

我还注意到,从 3.6 开始,所有词典都按照插入项目的顺序进行排序。

尽管从 3.6 开始订购字典,但您希望使用有序结构的某些语句似乎不起作用。

对我最有效的 OP 问题的答案。

itr = iter(dic.items())
lst = [next(itr) for i in range(3)]
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="")

不寻常的方法,因为它给出了强烈的 O(N) 时间复杂度。

如果d是您的字典,而n是印刷编号:

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

将字典转换为列表可能会很慢。 你的字典可能太大了,你不需要为了打印一些第一而把它全部投射出来。

您可以通过在字典上调用.items()来获取字典项。 然后将其转换为list ,然后像在任何列表中一样从那里获得前 N 个项目。

下面的代码打印字典对象的前 3 个项目

例如

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

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

print(first_three_items)

输出:

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

我喜欢这个,因为不需要创建新列表,它是一个完全符合您要求的衬垫,它适用于 python >= 3.8 (确实订购了字典,我认为从 python 3.6 开始?):

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

这适用于 python 3.8+:

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

您可以通过多种方式来解决这个问题。 如果顺序很重要,您可以这样做:

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

如果订单不是问题,您可以这样做:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM