2015-07-30 5 views
6

ich derzeit ein defaultdict von Counter bin mit eindeutig mehr unvorhersehbaren Werten für unberechenbar Schlüssel zählen:Wie verwendet man eine bestimmte Datenstruktur als default_factory für ein Defaultdict?

from collections import defaultdict, Counter 

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

Das gibt mir das erwartete Ergebnis:

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

Ich brauche jetzt die Struktur der erweitern Werte in der defaultdict und machen es eine dict mit zwei Tasten: die vorherige Counter und eine str:

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

Kann eine spezifische Datenstruktur (wie oben) als default_factory in defaultdict verwendet werden? Das erwartete Ergebnis wäre, dass für jeden nicht vorhandenen Schlüssel in defaultdict ein neuer Schlüssel und Wert erstellt würde, der mit der obigen Struktur initialisiert wurde.

+0

'defaultdict (lambda: {'counter': Zähler(), 'name': ''})'? – jonrsharpe

+0

@jonrsharpe: Das ist direkt vor Ort, ich habe nicht einmal daran gedacht, so zu gehen. Würde es Ihnen etwas ausmachen, das in eine Antwort zu kopieren? – WoJ

Antwort

8

Sie müssen nur Ihre default_factory als eine Funktion definieren, die das Wörterbuch, das Sie auf dem Standard wollen zurück:

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

Wenn Sie nicht vertraut mit Lambda-Ausdrücke sind, ist dies dasselbe wie:

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

eine alternative Lösung zu drootang ‚s Antwort eine benutzerdefinierte Klasse zu verwenden ist:

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 (< Klasse __main __ NamedCounter bei 0x19de808 >, { 'x': NamedCounter (name = 'X-Zähler', Zähler = Zähler ({ 'b': 2}))}.)

Alternativ können Sie Counter erweitern den Namen in den Zähler selbst zu übernehmen:

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 (<Klasse>, { 'x' '__main __ NamedCounter.': NamedCounter (name = 'x-Zähler', dict = {'b': 2})})

Verwandte Themen