2016-11-24 7 views
0

Ich habe Abfrageergebnisdaten im Format von Tupel von dict. Ich möchte die Daten in Tupel von Tupel des Diktats basierend auf bestimmten Bedingungen gruppieren.Konvertieren von Tupel von dict in Tupel von Tupel von Dict in Python

Echt Ausgang:

({'col1': 2014}, 
{'col1': 2013}, 
{'col1': 2014}, 
{'col1': 2013}, 
{'col1': 2015}, 
{'col2': '24'}) 

Erwartete Ausgabe: Hier gruppieren wir Basis für Jahr

(({'col1': 2014}, {'col1': 2014}), 
({'col1': 2013}, {'col1': 2013}), 
({'col1': 2015}, {'col2': '24'})) 

Bitte leiten uns die Daten zu erhalten, während wir die Abfrage anstelle der Verarbeitung einer verarbeiten durch man zeichnet auf und wandelt es in spezifisches Format um.

+1

Warum wollen Sie '{'col2': '24'}' in derselben Gruppe wie '2015' zu sein? –

+0

gleiche Zeile möglicherweise mehr die eine Spalte, also muss ich den Rest der Spalte auch gruppieren, aber ab sofort muss ich die Daten basierend auf Jahr gruppieren, einfach ignorieren 24. Ich brauche die Ausgabe als (({ 'col1': 2014}, {'col1': 2014}), ({'col1': 2013}, {'col1': 2013}), ({'col1': 2015}))) –

+0

Dann bitte [ bearbeite] deine Frage. –

Antwort

1

können Sie die dicts sortieren auf das Jahr und dann groupby verwenden mit Jahr key:

>>> from itertools import groupby 
>>> t = ({'col1':2014},{'col1':2013},{'col1':2014},{'col1':2013},{'col1':2015}) 
>>> key = lambda x: x['col1'] 
>>> tuple(tuple(g) for k, g in groupby(sorted(t, key=key), key)) 
(({'col1': 2013}, {'col1': 2013}), ({'col1': 2014}, {'col1': 2014}), ({'col1': 2015},)) 

groupby Wille Gruppe die aufeinanderfolgenden Elemente mit dem gleichen Schlüssel und (key, iterable) Tupel zurück. Dann wird jedes Iterable in ein Tupel innerhalb des Generatorausdrucks konvertiert, der als Parameter an tuple übergeben wird.

aktualisieren: Die obige Einzeiler hat O (n log n) Zeitkomplexität, da sie die Daten sortiert. Mit paar Zeilen kann die Aufgabe O (n) Zeit durch die Verwendung von defaultdict ergänzt:

>>> from collections import defaultdict 
>>> t = ({'col1':2014},{'col1':2013},{'col1':2014},{'col1':2013},{'col1':2015}) 
>>> dd = defaultdict(list) 
>>> for d in t: 
...  dd[d['col1']].append(d) 
... 
>>> tuple(tuple(v) for k, v in dd.items()) 
(({'col1': 2013}, {'col1': 2013}), ({'col1': 2014}, {'col1': 2014}),({'col1': 2015},)) 

Beachten Sie, dass dies die Gruppen in beliebiger Reihenfolge seit dict ist ungeordnete Sammlung zurück. Wenn Sie die Daten in "vollen" Gruppen verarbeiten müssen (nur eine Gruppe pro Jahr) und Sie die DB nicht dazu bringen können, die Daten in sortierter Reihenfolge zurückzugeben, ist dies das Beste, was Sie tun können.

Falls Sie die Daten aus der DB von Chargen in sortierter Reihenfolge bekommen, dann können Sie noch groupby verwenden, ohne alles zu ziehen vor:

from itertools import groupby 

cursor = iter([2013, 2013, 2014, 2014, 2014, 2015, 2015]) 

def get_batch(): 
    batch = [] 
    try: 
     for _ in range(3): 
      batch.append({'col1': next(cursor)}) 
    except StopIteration: 
     pass 

    print('Got batch') 
    return batch 

def fetch(): 
    while True: 
     batch = get_batch() 
     if not batch: 
      break 

     yield from batch 

for k, g in groupby(fetch(), lambda x: x['col1']): 
    print('Group: {}'.format(tuple(g))) 

Ausgang:

Got batch 
Group: ({'col1': 2013}, {'col1': 2013}) 
Got batch 
Group: ({'col1': 2014}, {'col1': 2014}, {'col1': 2014}) 
Got batch 
Got batch 
Group: ({'col1': 2015}, {'col1': 2015}) 
+0

Danke, die gegebene Lösung funktioniert gut. aber kann ich die Daten in der angegebenen zum Zeitpunkt der Abholung der Daten von db, anstatt jeden Datensatz durchlaufen und Sortieren der Daten und Gruppierung der gleichen, weil wir riesige Datenmengen haben, so wird es Zeit genommen werden Prozess . –

+0

@AsifNawaz Erweitert die Antwort ein wenig. Kurz gesagt, wenn Sie die DB dazu bringen können, die Daten in sortierter Reihenfolge zurückzugeben, dann können Sie 'groupby' verwenden, ohne alles vorher zu ziehen. Wenn die Daten in zufälliger Reihenfolge vorliegen, müssen Sie alles ziehen, aber Sie können die Sortierung überspringen, es sei denn, die Reihenfolge der Gruppen ist für Sie wichtig. – niemmi

+0

Vermissen Sie nicht den '24'-Eintrag, z. '({'col1': 2015}, {'col2': '24'}))'? – pylang