Considere o seguinte dicionário, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Desejo retornar a primeira N pares chave: valor de d (N <= 4 neste caso). Qual é o método mais eficiente de fazer isso?
Considere o seguinte dicionário, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Desejo retornar a primeira N pares chave: valor de d (N <= 4 neste caso). Qual é o método mais eficiente de fazer isso?
Respostas:
Não existe tal coisa de "primeiras n" chaves porque um dict
não lembra quais chaves foram inseridas primeiro.
Você pode obter quaisquer n pares de valores-chave:
n_items = take(n, d.iteritems())
Isso usa a implementação de take
das itertools
receitas :
from itertools import islice
def take(n, iterable):
"Return first n items of the iterable as a list"
return list(islice(iterable, n))
Veja funcionando online: ideone
Atualização para Python 3.6
n_items = take(n, d.items())
iteritems
deveria ser substituído por items
para pessoas no Python 3
take()
parte da base de código python em algum lugar? Ou é puramente a função que você definiu em sua resposta aqui? Perguntando como se fosse parte da base do código, não consigo localizar / importar. :)
Uma maneira muito eficiente de recuperar qualquer coisa é combinar as compreensões de lista ou dicionário com o fatiamento. Se você não precisa ordenar os itens (você só quer n pares aleatórios), você pode usar uma compreensão de dicionário como esta:
# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}
Geralmente, uma compreensão como essa é sempre mais rápida de executar do que o loop equivalente "for x in y". Além disso, ao usar .keys () para fazer uma lista das chaves do dicionário e dividir essa lista, você evita 'tocar' em quaisquer teclas desnecessárias ao construir o novo dicionário.
Se você não precisa das chaves (apenas os valores), você pode usar uma compreensão de lista:
first2vals = [v for v in mydict.values()[:2]]
Se você precisa dos valores classificados com base em suas chaves, não é muito mais problema:
first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]
ou se você também precisar das chaves:
first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
Os dict
s do Python não são ordenados, portanto, não faz sentido solicitar as "primeiras N" chaves.
A collections.OrderedDict
aula está disponível se você precisar. Você pode obter com eficiência seus primeiros quatro elementos, como
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
permite que você preguiçosamente pegue uma fatia de elementos de qualquer iterador. Se você quiser que o resultado seja reutilizável, você precisará convertê-lo em uma lista ou algo assim:
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))
Basicamente, transforme a visão (dict_items) em um iterador e, em seguida, itere com next ().
Não vi aqui. Não será ordenado, mas o mais simples sintaticamente se você precisar apenas pegar alguns elementos de um dicionário.
n = 2
{key:value for key,value in d.items()[0:n]}
TypeError: 'dict_items' object is not subscriptable
{key:value for key,value in stocks.items()[0:n]}
(ações é o nome do meu dicionário)
Para obter os N principais elementos de seu dicionário Python, pode-se usar a seguinte linha de código:
list(dictionaryName.items())[:N]
No seu caso, você pode alterá-lo para:
list(d.items())[:4]
Veja PEP 0265 sobre classificação de dicionários. Em seguida, use o código iterável mencionado anteriormente.
Se você precisar de mais eficiência nos pares de valores-chave classificados. Use uma estrutura de dados diferente. Ou seja, aquele que mantém a ordem de classificação e as associações de valor-chave.
Por exemplo
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)]
em py3, isso fará o truque
{A:N for (A,N) in [x for x in d.items()][:4]}
{'a': 3, 'b': 2, 'c': 3, 'd': 4}
Isso depende do que é "mais eficiente" no seu caso.
Se você quiser apenas uma amostra semi-aleatória de um dicionário enorme foo
, use foo.iteritems()
e retire quantos valores forem necessários, é uma operação preguiçosa que evita a criação de uma lista explícita de chaves ou itens.
Se você precisar classificar as chaves primeiro, não há como evitar o uso de algo como keys = foo.keys(); keys.sort()
ou sorted(foo.iterkeys())
, você terá que construir uma lista explícita de chaves. Em seguida, divida ou itere através dos primeiros Nkeys
.
BTW, por que você se preocupa com a maneira 'eficiente'? Você definiu o perfil do seu programa? Caso contrário, use primeiro o caminho óbvio e fácil de entender . Provavelmente, ele funcionará muito bem, sem se tornar um gargalo.
Você pode abordar isso de várias maneiras. Se o pedido for importante, você pode fazer o seguinte:
for key in sorted(d.keys()):
item = d.pop(key)
Se o pedido não for uma preocupação, você pode fazer o seguinte:
for i in range(4):
item = d.popitem()
value
vez de item
para maior clareza.
O dicionário não mantém nenhuma ordem, portanto, antes de escolher os N principais pares de valores-chave, vamos classificá-lo.
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
Agora podemos fazer a recuperação dos principais elementos 'N' :, usando a estrutura do método como esta:
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
para obter os 2 principais elementos, basta usar esta estrutura:
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)
considere um ditado
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
from itertools import islice
n = 3
list(islice(d.items(),n))
islice resolverá :) espero que ajude!
Isso pode não ser muito elegante, mas funciona para mim:
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
Tentei algumas das respostas acima e observe que algumas delas dependem da versão e não funcionam na versão 3.7.
Também observo que desde 3.6 todos os dicionários são ordenados pela sequência em que os itens são inseridos.
Apesar de os dicionários serem solicitados desde 3.6, algumas das instruções que você espera que funcionem com estruturas ordenadas parecem não funcionar.
A resposta à pergunta do OP que funcionou melhor para mim.
itr = iter(dic.items())
lst = [next(itr) for i in range(3)]
lst = list(d.items())[:N]
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="")
Abordagem incomum, pois dá complexidade de tempo O (N) intensa.
list(d.items())[:4]
. list () é a implementação subjacente para muitas das respostas.