2016-03-21 11 views
2

Ich bin mir nicht sicher, was ich so nennen soll, also sind auch Vorschläge zum Titel willkommen. Ich erstelle ein Programm, das Daten aus einer Datei liest und in der richtigen Reihenfolge ausgibt.Wörterbücher per Schlüssel numerisch mit einem bestimmten Format bestellen

Die Datei immer Daten auf dieser Basis enthalten:

  • Name: 1,2,3
  • Name_2: 4,5,6
  • NAME_3: 10,9,8

Hier ist mein Code für die Daten aus der Datei bekommen:

def getData(file): 
    data = {} 
    try: 
     with open(file + ".txt", "r") as file: 
      for line in file: 
       build = line.split(":") 
       data[build[0]] = build[1] 
    except FileNotFoundError: 
     with open(file + ".txt", "a") as file: 
      pass 
    return data 

Die zurückgegebenen Daten ist:

data = {"Name": "1,2,3\n", "Name_2": "4,5,6\n", "Name_3": "10,9,8\n" 

Nun, da ich die Daten habe, bin ich zu „sortieren“ versucht es, Wörterbücher sind nicht wirklich sortierbar so habe ich „OrderedDict.“ Heres der Code:

def sortData(data, choice): 
    ## Sort By Average 
    if choice == "Average": 
     for name, score in data.items(): 
      amount = 0 
      for i in re.finditer("[0-9]{1,2}", score): 
       amount += 1 
      average = eval(re.sub(",","+",score))/amount 
      data[name] = str(average) + "\n" 
     od_data = collections.OrderedDict(sorted(data.items(), key=lambda t:float(t[1]), reverse=True)) 
     for name, score in od_data.items(): 
      sys.stdout.write("%s: %s" % (name, score)) 
    ## Sort By Highest - Lowest 
    elif choice == "Highest - Lowest": 
     od_data = collections.OrderedDict(sorted(data.items(), key=lambda t:t[1], reverse=True)) 
     for name, score in od_data.items: 
      sys.stdout.write("%s: %s" % (name, score) 

Wenn die Wahl „Average“ ist, werden die Daten gedruckt, wie es nach und in Ordnung soll. Wenn die Wahl "Höchster - Niedrigster", werden die Daten teilweise um ausgedruckt:

  • Name_2: 4,5,6
  • Name: 1,2,3
  • NAME_3: 10,9 , 8

es funktioniert, wie es sollte, nur dann, wenn die erste „Nummer“ ist nicht „10“ ist, aus irgendeinem Grunde scheint es im Programm als „1“ und „0“ und endet daher bis registrieren sein als unterster Eintrag.

+0

Verwandte. http://stackoverflow.com/questions/4836710/does-python-have-a-built-in-function-for-string-natural-sort –

+0

Warum sprichst du nicht (', ')' und 'map' auf' int'? –

Antwort

0

Statt mit re und eval, könnten Sie einfach split die Saiten von , und map zu int (oder float), möglich ist, direkt beim Laden der Datei. Dann wird der Rest viel einfacher.

>>> data = {"Name": "1,2,3\n", "Name_2": "4,5,6\n", "Name_3": "10,9,8\n"} 
>>> data = {k: [int(x) for x in v.split(',')] for k, v in data.items()} 
>>> collections.OrderedDict(sorted(data.items(), key=lambda item: sum(item[1])/len(item[1]), reverse=True)) 
OrderedDict([('Name_3', [10, 9, 8]), ('Name_2', [4, 5, 6]), ('Name', [1, 2, 3])]) 

In Ihrem zweiten Teil für choice == "Highest - Lowest", ist nicht ganz klar, wie Sie sortieren möchten. Wenn Sie die Listen nach ihrer natürlichen Reihenfolge sortieren wollen - dh, vergleichen Sie das erste Element, und wenn diese gleich sind, und so weiter -, dann sortiere (data.items(), key = lambda t: t 1], reverse = True) in itself is correct, but t [1] from data ist immer noch eine Zeichenkette, also sortieren Sie nur nach der lexikographischen Reihenfolge dieser Zeichenketten. Sie müssen zuerst in Ganzzahllisten umwandeln, wie oben.

Wenn Sie stattdessen durch das Minimum der maximalen Element dieser Listen sortieren möchten, können Sie dies versuchen:

>>> collections.OrderedDict(sorted(data.items(), key=lambda item: min(item[1]))) # or max for maximum 

Beachten Sie auch, dass Sie benötigen, um das Ergebnis der Art in eine OrderedDict nicht einwickeln an alles, da du die Items sowieso nur iterierst. Arbeiten Sie einfach mit dem Ergebnis sorted direkt. Außerdem schlage ich vor, die Daten in Listen von vor Aufruf der Funktion geändert.Alles in allem könnten Sie Ihren Code zu etwas wie diesem ändern:

def sortData(data, choice): 
    sorters = {"Average": lambda item: sum(item[1])/len(item[1]), 
       "Highest - Lowest": lambda item: item[1], 
       "Minimum": lambda item: min(item[1]), 
       "Maximum": lambda item: max(item[1])} 
    if choice in sorters: 
     sorter = sorters[choice] 
     for name, score in sorted(data.items(), key=sorter, reverse=True): 
      print("%s: %s" % (name, score)) 
    else: 
     print("Unknown choice: " + choice) 

data = {"Name": "1,2,3\n", "Name_2": "4,5,6\n", "Name_3": "10,9,8\n"} 
data = {k: [int(x) for x in v.split(',')] for k, v in data.items()} 
sortData(data, "Minimum") 
+0

Danke dafür, ich habe das in meinen Code implementiert: 'Jeff: [10, 10, 10] Max: [9, 0] Harry: [5, 4] Henry: [5, 5, 5] und das ist erzeugt. Ich kann damit arbeiten und es im richtigen Format drucken, aber wie Sie sehen können, wird Harry vor Henry gedruckt. Wie kann ich es so machen, dass es sozusagen alle Zahlen berücksichtigt? –

+0

Ich könnte die Liste von der höchsten zur niedrigsten bestellen, obwohl ich denke, dass das nicht völlig helfen wird, irgendwelche Vorschläge? –

+0

@SylentNyte Wie haben Sie das bestellt? Maximalwert? In diesem Fall besteht eine Verbindung zwischen Harry und Henry. Wie willst du diese Krawatte "brechen"? Gesamtsumme? Anzahl der höchsten Elemente? Länge der Liste? –

0

Das Problem war, dass das Programm sie nicht basierend auf allen Werten bestellen würde. Ich habe einen Vorschlag für @tobias_k whih sehr hilfreich war und zurAufnahme und einen anderen Code mit ihm:

Abgeschlossen Code:

data = {k: [int(x) for x in v.split(',')] for k, v in data.items()} 
     od_data = collections.OrderedDict(sorted(data.items(), key=operator.itemgetter(1), reverse=True)) 
     print(od_data) 

Jetzt druckt:

OrderedDict ([('Jeff', [10, 10, 10]), ('Max', [9, 0]), ('Wie', [6, 2, 3]), ('Was', [6, 1]), ('Jefferson ", [6]), ('Henry', [5, 5, 5]), ('Warum', [5, 5, 4]), ('Harry', [5, 4])]])

(I einige Beispiele es richtig hinzugefügt testen)

Verwandte Themen