2017-04-03 4 views
2

Wenn der Typ eines Zählers Objekts Schlüssel zu addieren str ist, das heißt:ein einzelnes Zeichen Hinzufügen von Tasten in Counter

ich dies tun könnte:

>>> vocab_counter = Counter("the lazy fox jumps over the brown dog".split()) 

>>> vocab_counter = Counter({k+u"\uE000":v for k,v in vocab_counter.items()}) 
>>> vocab_counter 
Counter({'brown\ue000': 1, 
     'dog\ue000': 1, 
     'fox\ue000': 1, 
     'jumps\ue000': 1, 
     'lazy\ue000': 1, 
     'over\ue000': 1, 
     'the\ue000': 2}) 

Was für eine schnelle und/oder wäre pythonischer Weg, um allen Schlüsseln ein Zeichen hinzuzufügen?

Ist die obige Methode die einzige Möglichkeit, den letzten Zähler mit dem an alle Schlüssel angehängten Zeichen zu erreichen? Gibt es andere Wege, um dasselbe Ziel zu erreichen?

+3

Ich denke, die Art, wie Sie es tun, scheint ziemlich gut ... Welche Art von Verbesserungen erwarten Sie? Zeit genommen? Zeilen von Code? – Shadow

+0

Keine Codezeilen, nur die Frage, ob es einen besseren Weg gibt. Das mehrfache Durchlaufen aller Tasten ist nicht optimal. Vielleicht muss ich es auf einen Datenrahmen oder ein numpy Array ablegen und dann zurück zum Counter lesen. – alvas

+1

Ich denke nicht, dass das besser wäre ... Auf diese Weise würde man die Liste der geteilten Strings erstellen, jeden einzelnen manipulieren und dann zählen. Die Art und Weise, in der es gerade unten ist, berührt nur jedes einzelne Wort - wenn also ein Roman viel sauberer und effizienter wäre (meiner Meinung nach sowieso), würde ich nur ein Wörterbuch anstelle eines Zählers auf deinem letzten Schritt erstellen , da Sie nicht mehr zählen müssen (ich nehme an) – Shadow

Antwort

1

Der bessere Weg wäre, dieses Zeichen vor dem Erstellen Ihres Counter-Objekts hinzuzufügen. Sie können es tun, einen Generator Ausdruck innerhalb Counter mit:

In [15]: vocab_counter = Counter(w + u"\uE000" for w in "the lazy fox jumps over the brown dog".split()) 

In [16]: vocab_counter 
Out[16]: Counter({'the\ue000': 2, 'fox\ue000': 1, 'dog\ue000': 1, 'jumps\ue000': 1, 'lazy\ue000': 1, 'over\ue000': 1, 'brown\ue000': 1}) 

Wenn es nicht möglich ist, die Worte zu ändern, bevor der Zähler Erstellen Sie können die Counter Objekt um during setting the values for keys das Sonderzeichen hinzuzufügen, außer Kraft setzen.

1

Der einzige andere optimierte Weg, ich ist denken kann, eine Unterklasse von Counter zu verwenden, die den Charakter anfügt, wenn der Schlüssel eingefügt:

from collections import Counter 


class CustomCounter(Counter): 
    def __setitem__(self, key, value): 
     if len(key) > 1 and not key.endswith(u"\uE000"): 
      key += u"\uE000" 
     super(CustomCounter, self).__setitem__(key, self.get(key, 0) + value) 

Demo:

>>> CustomCounter("the lazy fox jumps over the brown dog".split()) 
CustomCounter({u'the\ue000': 2, u'fox\ue000': 1, u'brown\ue000': 1, u'jumps\ue000': 1, u'dog\ue000': 1, u'over\ue000': 1, u'lazy\ue000': 1}) 
# With both args and kwargs 
>>> CustomCounter("the lazy fox jumps over the brown dog".split(), **{'the': 1, 'fox': 3}) 
CustomCounter({u'fox\ue000': 4, u'the\ue000': 3, u'brown\ue000': 1, u'jumps\ue000': 1, u'dog\ue000': 1, u'over\ue000': 1, u'lazy\ue000': 1}) 
+2

Der CustomCounter in der Demo enthält den Eintrag 'u'the \ ue000 ': 1', der den Wert 2 haben sollte. Es scheint also, als ob in dieser Lösung ein Fehler aufgetreten ist. – Felix

+0

@Felix Oopsy! Fest. –

1

Kürzester Weg Ich verwendete ist,

vocab_counter = Counter("the lazy fox jumps over the brown dog".split()) 
for key in vocab_counter.keys(): 
    vocab_counter[key+u"\uE000"] = vocab_counter.pop(key) 
+0

Das ''\ ue000'' sollte am Ende jedes neuen Schlüssels sein, nicht an der Vorderseite. –

+0

Yah! Sie können dies als Tippfehler betrachten: P – DexJ

+0

Jetzt, wo das behoben wurde, denke ich, das ist die einzige fehlerfreie Antwort hier. Ich denke nicht, dass diese Methode besser ist als das, was in der Frage war, aber zumindest ist es nicht schlimmer. –

0

Sie könnten es mit String-Manipulationen tun:

Verwandte Themen