2015-10-27 21 views
7

pop è una grande piccola funzione che, se utilizzata nei dizionari (con una chiave conosciuta) rimuove l'elemento con quella chiave dal dizionario e restituisce anche il valore corrispondente. Ma cosa succede se voglio anche la chiave?Neat way of popping key, valore PAIR dal dizionario?

Ovviamente, nei casi più semplici probabilmente potrei solo fare qualcosa di simile:

pair = (key, some_dict.pop(key)) 

Ma se, per esempio, ho voluto per estrarre la coppia chiave-valore con il valore più basso, seguendo l'idea di cui sopra lo farei hanno a che fare questo ...

pair = (min(some_dict, key=some.get), some_dict.pop(min(some_dict, key=some_dict.get))) 

... che è orrendo come devo fare l'operazione per due volte (ovviamente ho potuto memorizzare l'output da min in una variabile, ma non sono ancora completamente soddisfatto quella). Quindi la mia domanda è: c'è un modo elegante per farlo? Mi sto perdendo un trucco ovvio qui?

+0

negozio l'output di 'min' in una variabile – JBernardo

+1

@Bernardo ci avevo pensato. Ovviamente è meglio, ma sento che dovrebbe esserci un modo migliore senza uno. –

+1

Si potrebbe desiderare un heap, piuttosto che un 'dict'. Vedi il modulo 'heapq'. – chepner

risposta

3

È possibile definire te stesso oggetto utilizzando dizionario python ABC s, che fornisce l'infrastruttura per la definizione abstract base classes. E poi sovraccaricare l'attributo pop di oggetti dizionario Python base alle proprie esigenze:

from collections import Mapping 

class MyDict(Mapping): 
    def __init__(self, *args, **kwargs): 
     self.update(dict(*args, **kwargs)) 

    def __setitem__(self, key, item): 
     self.__dict__[key] = item 

    def __getitem__(self, key): 
     return self.__dict__[key] 

    def __delitem__(self, key): 
     del self.__dict__[key] 

    def pop(self, k, d=None): 
     return k,self.__dict__.pop(k, d) 

    def update(self, *args, **kwargs): 
     return self.__dict__.update(*args, **kwargs) 

    def __iter__(self): 
     return iter(self.__dict__) 

    def __len__(self): 
     return len(self.__dict__) 

    def __repr__(self): 
     return repr(self.__dict__) 

Demo:

d=MyDict() 

d['a']=1 
d['b']=5 
d['c']=8 

print d 
{'a': 1, 'c': 8, 'b': 5} 

print d.pop(min(d, key=d.get)) 
('a', 1) 

print d 
{'c': 8, 'b': 5} 

Nota: Come @chepner suggerito nel commento come una scelta migliore è possibile ignorare popitem, che restituisce già una coppia chiave/valore.

+0

Sarebbe meglio sovrascrivere 'popitem', che già restituisce una coppia chiave/valore, e permettergli di prendere un argomento chiave opzionale. – chepner

+0

@chepner Sì, sarebbe meglio. Ho appena mostrato la strada. – Kasramvd

+1

Grazie, accettato in quanto ha dato una soluzione al problema generale. –

3

Un heap supporta l'operazione pop-min che descrivi. Tuttavia, dovrai prima creare un heap dal tuo dizionario.

import heapq 
# Must be two steps; heapify modifies its argument in-place. 
# Reversing the key and the value because the value will actually be 
# the "key" in the heap. (Or rather, tuples are compared 
# lexicographically, so put the value in the first position.) 
heap = [(v, k) for k, v in some_dict.items()] 
heapq.heapify(heap) 

# Get the smallest item from the heap 
value, key = heapq.heappop(heap) 
+0

Grazie per aver risposto. Questo è ottimo per il minimo, ma questo era solo un esempio del problema più generale di scattare sia la chiave che il valore, dato un certo tasto (scusa se non era chiaro). La soluzione ideale sarebbe in grado di fare la stessa cosa con altri criteri. –

+0

@ J.F.Sebastian Oops. Lo sapevo, ma mentre provavo qualcosa mi sono reso pigro e ho dimenticato che 'heap' era solo una lista il cui ordine era suscettibile alle funzioni' heapq', piuttosto che un'istanza di un tipo di heap distinto. – chepner

1

qui è un'implementazione più semplice

class CustomDict(dict): 
    def pop_item(self, key): 
     popped = {key:self[key]} #save "snapshot" of the value of key before popping 
     self.pop(key) 
     return popped 

a = CustomDict() 
b = {"hello":"wassup", "lol":"meh"} 
a.update(b) 
print(a.pop_item("lol")) 
print(a) 

Quindi qui abbiamo creato una consuetudine dict che si apre l'elemento desiderato e dà fuori la coppia chiave-valore

+1

Si prega di aggiungere qualche spiegazione! –

+0

ok wilco Aggiungerò alcune spiegazioni – Zion

Problemi correlati