2015-07-30 6 views
6

Attualmente sto usando un defaultdict di Counter contare unicamente diversi valori imprevedibili per le chiavi imprevedibili:Come utilizzare una struttura dati specifica come default_factory per un valore predefinito?

from collections import defaultdict, Counter 

d = defaultdict(Counter) 
d['x']['b'] += 1 
d['x']['c'] += 1 
print(d) 

Questo mi dà il risultato previsto:

defaultdict(<class 'collections.Counter'>, {'x': Counter({'c': 1, 'b': 1})}) 

Ora ho bisogno di ampliare la struttura del valori nel numero defaultdict e convertirlo in dict con due chiavi: il precedente Counter e uno str:

mystruct = { 
    'counter': collections.Counter(), 
    'name': '' 
} 

È possibile utilizzare una struttura dati specifica (come sopra) come default_factory in defaultdict? Il risultato previsto sarebbe che per ogni chiave inesistente nello defaultdict, si creerebbe una nuova chiave e un valore inizializzati con la struttura precedente.

+0

'defaultdict (lambda: {'counter': Counter(), 'name': ''}}'? – jonrsharpe

+0

@jonrsharpe: questo è giusto, non ho nemmeno pensato di andare in quel modo. Ti dispiacerebbe copiare questo in una risposta? – WoJ

risposta

8

Hai solo bisogno di definire il default_factory come una funzione che restituisce il dizionario da default:

from collections import defaultdict, Counter 
d = defaultdict(lambda: {'counter': Counter(), 'name': ''}) 
d['x']['counter']['b'] += 1 
d['x']['counter']['c'] += 1 
print(d) 

Se non si ha familiarità con lambda, questa è la stessa cosa di:

def my_factory(): 
    aDict = {'counter': Counter(), 'name':''} 
    return aDict 
d = defaultdict(my_factory) 
1

una soluzione alternativa per drootang 's risposta è quella di utilizzare una classe personalizzata:

from collections import defaultdict, Counter 

class NamedCounter: 
    def __init__(self, name = '', counter = None): 
     self.counter = counter if counter else Counter() 
     self.name = name 

    def __repr__(self): 
     return 'NamedCounter(name={}, counter={})'.format(
       repr(self.name), repr(self.counter)) 

d = defaultdict(NamedCounter) 
d['x'].counter['b'] += 1 
d['x'].counter['b'] += 1 
d['x'].name = 'X counter' 
print(d) 

defaultdict (< classe __main __ NamedCounter a 0x19de808 >, { 'x': NamedCounter (name = 'contatore X', il contatore = contatore ({ 'b': 2}))}.)

in alternativa, è possibile estendere Counter per incorporare il nome nel contatore stesso:

from collections import defaultdict, Counter 

class NamedCounter(Counter): 
    def __init__(self, name = '', dict = None): 
     super(Counter, self).__init__(dict if dict else {}) 
     self.name = name 

    def __repr__(self): 
     return 'NamedCounter(name={}, dict={})'.format(
       repr(self.name), super(Counter, self).__repr__()) 

d = defaultdict(NamedCounter) 
d['x']['b'] += 1 
d['x']['b'] += 1 
d['x'].name = 'X counter' 
print(d) 

defaultdict (<class>, { 'x' '__main __ NamedCounter.': NamedCounter (name = 'contatore x', dict = {'b': 2})})

Problemi correlati