2016-04-23 2 views
0

Ich habe eine Funktion buildFrequencyList, die wie folgt funktionieren sollte:Python - Erstellen Sie eine Tupel-Liste nach den Zeichen Frequenzen im Eingangs

>>> L = [] 
>>> buildFrequencyList(L, 'bbaabtttaabtctce') 
>>> L 
[(4, 'b'), (4, 'a'), (5, 't'), (2, 'c'), (1, 'e')] 

Hier ist der Code:

def buildFrequencyList(outputList, dataIN): 
    for c in dataIN: 
     a = 1 
     bo = True 
     if outputList == []: 
      outputList.append((a,c)) 
     for i in outputList: 
      (a,b) = i 
      if b==c: 
       bo= False 
       a +=1 
     if(bo): 
      outputList.append((1,c))  
    return outputList 

Aber der Ausgang tatsächlich ist:

[(1, 'b'), (1, 'a'), (1, 't'), (1, 'c'), (1, 'e')] 

Ich weiß nicht warum. Kann mir jemand erklären, was das Problem ist?

bearbeiten:

modifizierte ich den Code, und ich habe wirklich merkwürdige Ausgabe:

def buildFrequencyList(outputList, dataIN): 
    for c in range(len(dataIN)): 
     if outputList == []: 
      outputList.append((1,dataIN[c])) 
     for i in range(len(outputList)): 
      (a,b) = outputList[i] 
      if b==dataIN[c]: 
       outputList[i] = (a+1,b) 
      else:   
       outputList.append((1,dataIN[c]))  
    return outputList 

die Ausgabe:

[(5, 'b'), (4, 'a'), (3, 'a'), (2, 'b'), (2, 'b'), (5, 't'), (5, 't'), (5, 't'), (5, 't'), (5, 't'), (4, 't')...] # is infinite 
+0

Welche Ausgabe haben Sie erwartet? – jonrsharpe

+0

[(4, 'b'), (4, 'a'), (5, 't'), (2, 'c'), (1, 'e')] –

+0

Aber Sie aktualisieren nie tatsächlich die Werte In der Liste. Tupel und ganze Zahlen sind * unveränderlich *. – jonrsharpe

Antwort

0

Schauen wir uns den Code:

def buildFrequencyList(outputList, dataIN): 
    for c in dataIN: 
     a = 1 
     bo = True 
     if outputList == []: 
      outputList.append((a,c)) 
     for i in outputList: 
      (a,b) = i 
      if b==c: 
       bo= False 
       a +=1 
     if(bo): 
      outputList.append((1,c))  
    return outputList 

Lassen Sie uns jetzt einige Fälle in Betracht ziehen. Zuerst wird der Fall, die outputList leer ist:

a = 1 
bo = True 
if outputList == []: 
    outputList.append((a,c)) 

Jetzt bemerken, dass es niemals einen Wert in a andere als 1. Dies ist einer der Fälle, wo es okay ist, eine „magische Zahl“ zu verwenden, da Es sollte offensichtlich sein, dass Sie Dinge zählen (basierend auf dem Funktionsnamen, da Sie keine Dokumente bereitstellen).

if outputList == []: 
    outputList.append((1,c)) 

Aber warte! Weil die for-Schleife in einer leeren Liste null Mal ausgeführt wird. Also der Code unten:

if (bo): 
    outputList.append((1,c)) 

würde den gleichen Job wie dieser Code machen. Dieser Code ist völlig unnötig. Löschen Sie es einfach.

Nun, was ist, wenn die outputList nicht leer ist?

for i in outputList: 
    (a,b) = i 
    if b == c: 
     bo = False 
     a += 1 

Was macht das? Es erhöht a, was in Ordnung ist - die Anzahl ist eine höhere. Es setzt bo auf False, um etwas anzuzeigen. Ich vermute, dass Sie einen Eintrag in der Liste gefunden haben, so dass ein neues Objekt nicht benötigt wird.

Was passiert dann mit a?

if (bo): 
     outputList.append((1,c)) 
return outputList 

NICHTS! Sie verwenden nie wieder a.

Also gibt es Ihr Problem: Die Zeiten, wenn Sie bereits einen Eintrag in der Liste haben, aktualisieren Sie es nie.

Wie können Sie es beheben?

Die kurze Antwort ist, dass Sie nicht können. Weil Tupel unveränderlich sind. Das bedeutet, dass Sie die in einem Tupel gespeicherten Werte nicht ändern (oder "ändern" können). Sie müssen das Tupel wegwerfen und ein neues mit den richtigen Werten erstellen.

Eine Lösung könnte zu .remove() sein das Tupel aus der Liste, und fügen Sie dann ein neues Tupel (a,c) nach a erhöht wird.

for tpl in outputList: 
    freq,val = tpl 
    if val == c: 
     outputList.remove(tpl) # INVALIDATES FOR LOOP! MUST BREAK! 
     outputList.append((freq+1,val)) 
     bo = False 
     break 

könnte andere Lösung zu verwenden enumerate(outputList) sein, das Tupel wie folgt einen Index und ein Wert zu erhalten, dann überschreiben:

for i, freq in outputList: 
    if freq[1] == c: 
     outputList[i] = (freq[0]+1, freq[1]) 
     break 

Eine andere Wahl wäre, die Frequenzinformationen in einem separaten Behälter zu halten, Wie ein Wörterbuch, bis Sie eine "letzte" Zählung haben, dann gehen Sie durch und fügen Sie alle Zählungen gleichzeitig der Liste hinzu.

counts = collections.defaultdict(0) 
for c in dataIN: 
    counts[c] += 1 
for char,count in counts.items(): 
    outputList.append((count,char)) 
1

Sie Ihre Liste nicht aktualisiert wird, und stattdessen Ihre lokale Variablen. Sie machen auch viele unnötige Berechnungen. (Siehe @ jonrsharpe Kommentar)

Ein klarer Weise die gewünschte Ausgabe wäre zu erreichen:

def build_frequency_list(s): 
    return [(s.count(c), c) for c in sorted(set(s))] 

Ergebnis:

>>> [(s.count(c), c) for c in sorted(set(s))] 
[(4, 'a'), (4, 'b'), (2, 'c'), (1, 'e'), (5, 't')] 
+0

Ich kann die Zählfunktion nicht verwenden. Ich möchte meinen eigenen Code erstellen –

+0

Warum können Sie es nicht verwenden? Es gibt einen Grund, warum solche Methoden in der Standardbibliothek vorhanden sind. – tobspr

+0

Weil ich ein Student bin und das Ziel ist, diese Funktion ohne Zählung zu codieren –

0

Was ist das?

from collections import defaultdict 

s = 'bbaabtttaabtctce' 
d = defaultdict(int) 
for c in s: 
    d[c] += 1 
d.items() 

Die offensichtliche Antwort ist

from collections import Counter 

Counter(s).items() 

aber Sie sagten, Sie nicht verwenden können.

+0

Ich kann Dictionnary nicht verwenden –

Verwandte Themen