Bei der Entwicklung einer Webanwendung wird häufig ein Prozess implementiert, der das Ergebnis der Ausführung einer SQL-Abfrage so formatiert, dass es mit der Antwort der API übereinstimmt.
Ich denke, dass die Daten, die als Ergebnis der Ausführung der SQL-Abfrage erhalten werden, meistens eine Liste von Instanzen sind, die vom Treiber definiert wurden, der für die DB-Verbindung verwendet wird, aber das Formatieren dieser Daten ist unerwartet mühsam. Ich denke es gibt viele. (Der Großteil der Verarbeitung selbst ist einfach, daher fühle ich mich oft so.)
In diesem Artikel habe ich untersucht, wie der obige Datenformatierungsprozess effizient implementiert werden kann.
Zum Beispiel, wenn die folgenden Daten von der DB abgerufen werden können Überlegen Sie, diese Daten zu gestalten.
data_list = [
{
'user_id': 1,
'group_name': 'GroupA',
'user_name': 'user1',
'email': '[email protected]'
},
{
'user_id': 2,
'group_name': 'GroupB',
'user_name': 'user2',
'email': '[email protected]'
},
{
'user_id': 3,
'group_name': 'GroupB',
'user_name': 'user3',
'email': '[email protected]'
},
{
'user_id': 4,
'group_name': 'GroupA',
'user_name': 'user4',
'email': '[email protected]'
},
{
'user_id': 5,
'group_name': 'GroupA',
'user_name': 'user5',
'email': '[email protected]'
}
]
Die erwarteten Ergebnisse wurden wie unten gezeigt nach Gruppennamen gruppiert Es wird in Formatdaten konvertiert.
{
"GroupA": [
{
"user_id": 1,
"user_name": "user1",
"email": "[email protected]"
},
{
"user_id": 4,
"user_name": "user4",
"email": "[email protected]"
},
{
"user_id": 5,
"user_name": "user5",
"email": "[email protected]"
}
],
"GroupB": [
{
"user_id": 2,
"user_name": "user2",
"email": "[email protected]"
},
{
"user_id": 3,
"user_name": "user3",
"email": "[email protected]"
}
]
}
Ich habe die folgenden zwei Muster als Methode zur Implementierung der Formverarbeitung untersucht.
Ich denke, der einfachste Weg zu schreiben ist, die Daten einzeln in die for-Anweisung zu packen, wie unten gezeigt.
#Das Argument sind die von der DB erhaltenen Daten
def sample1(data_list):
result_dict = {}
for data in data_list:
group_name = data.get('group_name')
# group_Überlegung, wenn der Name nicht registriert ist
if group_name not in result_dict:
result_dict[group_name] = []
# group_Generieren Sie ein Wörterbuch ohne Namen und fügen Sie es der Liste hinzu
result_dict[group_name].append({key:value for key, value in data.items() if key != 'group_name'})
return result_dict
Dieser Formatierungsprozess kann auch mithilfe von Reduzieren implementiert werden.
from functools import reduce
#Das Argument sind die von der DB erhaltenen Daten
def sample2(data_list):
def accumulate(total, target):
group_name = target.get('group_name')
# group_Überlegung, wenn der Name nicht registriert ist
if group_name not in total:
total[group_name] = []
# group_Generieren Sie ein Wörterbuch ohne Namen und fügen Sie es der Liste hinzu
total[group_name].append({key:value for key, value in target.items() if key != 'group_name'})
return total
return reduce(accumulate, data_list, {})
Um diese Implementierung kurz zu erläutern, kann reduct eine Funktion als erstes Argument, Daten als zweites Argument und einen optionalen Anfangswert als drittes Argument übergeben, sodass sie von der Datenformatierungsfunktion (akkumulieren) DB erhalten wurden. Daten (data_list), ein leeres Wörterbuch wird als Anfangswert übergeben. Wenn dann zum ersten Mal akkumulieren aufgerufen wird, wird ein leeres Wörterbuch an total übergeben, die ersten Daten von data_list werden an target übergeben und der vorherige Rückgabewert wird nach dem zweiten Mal auf total gesetzt. Werden.
Der Vorteil des Schreibens von Muster 1 besteht darin, dass es durch jeden Formatierungsprozess implementiert werden kann. Der Nachteil ist jedoch, dass es jedes Mal implementiert werden muss, wenn ein Formatierungsprozess wie dieser erforderlich ist (geringe Wiederverwendbarkeit). Ich denke.
Andererseits kann das Schreiben von Muster 2 die Lesbarkeit bei der Implementierung einer komplizierten Verarbeitung verringern, aber die Formatierungsverarbeitung ist üblich, indem der Spaltenname, auf den die Datenformatierungsfunktion verweist, dynamisch geändert wird. Der Vorteil ist, dass es konvertiert werden kann.
Gibt es auch kein Problem mit der Geschwindigkeit bei der Verwendung von Reduzieren? Weil es Bedenken gab Für alle Fälle habe ich die Zeit gemessen, die zum Formatieren der Daten von 10000000 Datensätzen für jedes Muster benötigt wird. * Implementiert mit Jupyter Notebook
%timeit sample1(data_list)
11.6 s ± 211 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit sample2(data_list)
12.3 s ± 290 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Aus dem obigen Ausführungsergebnis wurde festgestellt, dass die Implementierung mit Reduce etwas langsamer ist. Trotzdem gibt es bei 10000000-Datensatzdaten nur einen Unterschied von etwa 1 Sekunde, sodass Sie sich keine Gedanken über die Geschwindigkeit machen müssen. Überlegen.
Abschließend abschließend Ich halte es für realistisch, auf eine komplizierte Verarbeitung zu verzichten und die for-Anweisung zu verwenden, während die zu verwendende Grundrichtlinie so weit wie möglich reduziert wird, um die Verarbeitung zu standardisieren.
Recommended Posts