Lors du développement d'une application Web, il est courant d'implémenter un processus qui formate le résultat de l'exécution d'une requête SQL afin qu'il corresponde à la réponse de l'API.
Je pense que les données obtenues à la suite de l'exécution de la requête SQL sont principalement une liste d'instances définies par le pilote utilisé pour la connexion à la base de données, mais le processus de formatage de ces données est inopinément gênant. Je pense qu'il y en a beaucoup. (La plupart du traitement lui-même est simple, donc je pense souvent de cette façon.)
Dans cet article, j'ai examiné comment implémenter efficacement le processus de formatage des données ci-dessus.
Par exemple, si les données suivantes peuvent être obtenues à partir de la base de données Pensez à façonner ces données.
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]'
}
]
Les résultats attendus ont été regroupés par nom_groupe comme indiqué ci-dessous Il sera converti en données de format.
{
"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]"
}
]
}
J'ai examiné les deux modèles suivants comme méthode de mise en œuvre du traitement de mise en forme.
Je pense que le moyen le plus simple d'écrire est de regrouper les données une par une dans l'instruction for comme indiqué ci-dessous.
#L'argument est les données obtenues de la base de données
def sample1(data_list):
result_dict = {}
for data in data_list:
group_name = data.get('group_name')
# group_Considération lorsque le nom n'est pas enregistré
if group_name not in result_dict:
result_dict[group_name] = []
# group_Générer un dictionnaire excluant le nom et l'ajouter à la liste
result_dict[group_name].append({key:value for key, value in data.items() if key != 'group_name'})
return result_dict
Ce processus de formatage peut également être implémenté à l'aide de la méthode Reduce.
from functools import reduce
#L'argument est les données obtenues de la base de données
def sample2(data_list):
def accumulate(total, target):
group_name = target.get('group_name')
# group_Considération lorsque le nom n'est pas enregistré
if group_name not in total:
total[group_name] = []
# group_Générer un dictionnaire excluant le nom et l'ajouter à la liste
total[group_name].append({key:value for key, value in target.items() if key != 'group_name'})
return total
return reduce(accumulate, data_list, {})
Pour expliquer brièvement cette implémentation, la réduction peut passer une fonction comme premier argument, des données comme deuxième argument et une valeur initiale facultative comme troisième argument, elle a donc été obtenue à partir de la fonction de formatage des données (accumuler), DB. Data (data_list), un dictionnaire vide est passé comme valeur initiale. Ensuite, lorsque l'accumulation est appelée pour la première fois, un dictionnaire vide est passé à total, les premières données de data_list sont passées à la cible et la valeur de retour précédente est définie pour total après la deuxième fois. Devenir.
L'avantage d'écrire le modèle 1 est qu'il peut être implémenté par n'importe quel processus de formatage, mais l'inconvénient est qu'il doit être implémenté chaque fois qu'un processus de formatage comme celui-ci est requis (faible réutilisabilité). Je pense.
D'autre part, la manière d'écrire le motif 2 peut réduire la lisibilité lors de la mise en œuvre d'un traitement compliqué, mais le traitement de formatage est courant en changeant dynamiquement le nom de colonne référencé par la fonction de formatage de données. L'avantage est qu'il peut être converti.
N'y a-t-il pas non plus un problème de vitesse lors de l'utilisation de la réduction? Parce qu'il y avait un souci Au cas où, j'ai mesuré le temps nécessaire pour formater les données de 10000000 enregistrements pour chaque modèle. * Implémenté avec le notebook jupyter
%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)
À partir du résultat d'exécution ci-dessus, il a été constaté que la mise en œuvre utilisant réduire est un peu plus lente, mais même ainsi, il n'y a qu'une différence d'environ 1 seconde avec 10000000 données d'enregistrement, vous n'avez donc pas à vous soucier de la vitesse. pense.
De ce qui précède, en conclusion Je pense qu'il est réaliste de renoncer au traitement compliqué et d'utiliser l'instruction for tout en faisant en sorte que la politique de base à utiliser réduise autant que possible pour normaliser le traitement.
Recommended Posts