Considera il seguente dizionario, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Voglio restituire la prima chiave N: coppie di valori da d (N <= 4 in questo caso). Qual è il metodo più efficiente per farlo?
Considera il seguente dizionario, d:
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
Voglio restituire la prima chiave N: coppie di valori da d (N <= 4 in questo caso). Qual è il metodo più efficiente per farlo?
Risposte:
Non esiste una cosa del genere per le "prime n" chiavi perché a dict
non ricorda quali chiavi sono state inserite per prime.
È possibile ottenere tutte le coppie chiave-valore n però:
n_items = take(n, d.iteritems())
Questo utilizza l'implementazione di take
dalle itertools
ricette :
from itertools import islice
def take(n, iterable):
"Return first n items of the iterable as a list"
return list(islice(iterable, n))
Guardalo in linea: ideone
Aggiornamento per Python 3.6
n_items = take(n, d.items())
iteritems
dovrebbe essere sostituito con items
per gente su Python 3
take()
parte della base del codice Python da qualche parte? Oppure è puramente la funzione che hai definito nella tua risposta qui? Chiedendo come se fosse una parte del codice di base, non sono in grado di trovarlo / importarlo. :)
Un modo molto efficiente per recuperare qualsiasi cosa è combinare le comprensioni di elenchi o dizionari con l'affettatura. Se non hai bisogno di ordinare gli articoli (vuoi solo n coppie casuali), puoi usare una comprensione del dizionario come questa:
# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}
Generalmente una comprensione come questa è sempre più veloce da eseguire rispetto all'equivalente ciclo "for x in y". Inoltre, usando .keys () per creare un elenco delle chiavi del dizionario e affettando quell'elenco, eviti di "toccare" qualsiasi tasto non necessario quando crei il nuovo dizionario.
Se non hai bisogno delle chiavi (solo dei valori) puoi usare una comprensione dell'elenco:
first2vals = [v for v in mydict.values()[:2]]
Se hai bisogno dei valori ordinati in base alle loro chiavi, non c'è molto più problema:
first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]
o se hai bisogno anche delle chiavi:
first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}
Le dict
chiavi di Python non sono ordinate, quindi non ha senso chiedere le "prime N" chiavi.
La collections.OrderedDict
classe è disponibile se è quello che ti serve. Puoi ottenere in modo efficiente i suoi primi quattro elementi come
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
ti permette di prendere pigramente una fetta di elementi da qualsiasi iteratore. Se vuoi che il risultato sia riutilizzabile, devi convertirlo in un elenco o qualcosa del genere, in questo modo:
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))
Fondamentalmente, trasforma la vista (dict_items) in un iteratore, quindi itera con next ().
Non l'ho visto qui. Non verrà ordinato ma sintatticamente il più semplice se è necessario prendere solo alcuni elementi da un dizionario.
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]}
(stock è il nome del mio dizionario)
Per ottenere i primi N elementi dal tuo dizionario Python, puoi usare la seguente riga di codice:
list(dictionaryName.items())[:N]
Nel tuo caso puoi cambiarlo in:
list(d.items())[:4]
Vedere PEP 0265 sull'ordinamento dei dizionari. Quindi utilizzare il suddetto codice iterabile.
Se hai bisogno di maggiore efficienza nelle coppie chiave-valore ordinate. Usa una struttura dati diversa. Ovvero, uno che mantiene l'ordine ordinato e le associazioni valore-chiave.
Per esempio
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)]
in py3, questo farà il trucco
{A:N for (A,N) in [x for x in d.items()][:4]}
{'a': 3, 'b': 2, 'c': 3, 'd': 4}
Dipende da cosa è "più efficiente" nel tuo caso.
Se vuoi solo un campione semi-casuale di un enorme dizionario foo
, usa foo.iteritems()
e prendi tutti i valori di cui hai bisogno, è un'operazione pigra che evita la creazione di un elenco esplicito di chiavi o elementi.
Se devi prima ordinare le chiavi, non c'è modo di usare qualcosa come keys = foo.keys(); keys.sort()
o sorted(foo.iterkeys())
, dovrai creare un elenco esplicito di chiavi. Poi tagliare o iterare primo N keys
.
BTW perché ti interessa il modo "efficiente"? Hai profilato il tuo programma? Se non l'hai fatto, usa prima il modo ovvio e facile da capire . È probabile che andrà abbastanza bene senza diventare un collo di bottiglia.
Puoi avvicinarti a questo in molti modi. Se l'ordine è importante, puoi farlo:
for key in sorted(d.keys()):
item = d.pop(key)
Se l'ordine non è un problema, puoi farlo:
for i in range(4):
item = d.popitem()
value
piuttosto che item
per chiarezza.
Il dizionario non mantiene l'ordine, quindi prima di scegliere le prime N coppie di valori chiave, è necessario ordinarlo.
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
Ora possiamo recuperare i primi 'N' elementi :, usando la struttura del metodo in questo modo:
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
per ottenere i primi 2 elementi, usa semplicemente questa struttura:
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)
considera un dict
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
from itertools import islice
n = 3
list(islice(d.items(),n))
islice farà il trucco :) spero che aiuti!
Questo potrebbe non essere molto elegante, ma per me funziona:
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
Ho provato alcune delle risposte sopra e ho notato che alcune dipendono dalla versione e non funzionano nella versione 3.7.
Noto anche che dalla 3.6 tutti i dizionari sono ordinati in base alla sequenza in cui sono inseriti gli elementi.
Nonostante i dizionari siano stati ordinati a partire dalla versione 3.6, alcune delle affermazioni che ci si aspetta funzionino con strutture ordinate non sembrano funzionare.
La risposta alla domanda OP che ha funzionato meglio per me.
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="")
Approccio insolito, poiché emette un'intensa complessità del tempo O (N).
list(d.items())[:4]
. list () è l'implementazione sottostante per molte delle risposte.