Table des matières
Contenu de la question
Solution
Maison développement back-end Golang Convertir les valeurs séparées par des points en structure Go à l'aide de Python

Convertir les valeurs séparées par des points en structure Go à l'aide de Python

Feb 10, 2024 pm 01:33 PM
go语言

使用 Python 将点分隔值转换为 Go 结构

Dans cet article, l'éditeur PHP Youzi vous présentera comment utiliser Python pour convertir des valeurs séparées par des points (telles que "key1.subkey1.subkey2") en une structure dans le langage Go. Ce processus de transformation est utile pour extraire et traiter les données des fichiers de configuration ou des réponses API. Nous utiliserons les fonctions récursives de Python et les structures du langage Go pour implémenter cette conversion, et donnerons des exemples de code et des explications détaillés. Après avoir étudié cet article, les lecteurs seront en mesure de traiter et de convertir facilement des valeurs séparées par des points, améliorant ainsi l'efficacité et la flexibilité du traitement des données.

Contenu de la question

Il s'agit d'une exigence spécifique pour une application qui peut changer de configuration (en particulier le serveur d'identité wso2, puisque j'utilise go pour écrire l'opérateur kubernetes pour cela). Mais ce n'est vraiment pas pertinent ici. Je souhaite créer une solution permettant de gérer facilement un grand nombre de cartes de configuration pour générer des structures go. Ces configurations sont mappées en .csv

Lien vers .csv - my_configs.csv

Je veux, Écrivez un script python qui génère automatiquement des structures go afin que toute modification apportée à la configuration de l'application puisse être mise à jour en exécutant simplement le script python pour créer la structure go correspondante. Je fais référence à la configuration de l'application elle-même. Par exemple, les noms de clés toml en csv peuvent être modifiés/de nouvelles valeurs peuvent être ajoutées.

Jusqu'à présent, j'ai créé avec succès un script python qui atteint presque mon objectif. Le script est,

import pandas as pd

def convert_to_dict(data):
    result = {}
    for row in data:
        current_dict = result
        for item in row[:-1]:
            if item is not none:
                if item not in current_dict:
                    current_dict[item] = {}
                current_dict = current_dict[item]
    return result

def extract_json_key(yaml_key):
    if isinstance(yaml_key, str) and '.' in yaml_key:
        return yaml_key.split('.')[-1]
    else:
        return yaml_key

def add_fields_to_struct(struct_string,go_var,go_type,json_key,toml_key):
    struct_string += str(go_var) + " " + str(go_type) + ' `json:"' + str(json_key) + ',omitempty" toml:"' +str(toml_key) + '"` ' + "\n"
    return struct_string

def generate_go_struct(struct_name, struct_data):
    struct_name="configurations" if struct_name == "" else struct_name
    struct_string = "type " + struct_name + " struct {\n"
    yaml_key=df['yaml_key'].str.split('.').str[-1]
    
    # base case: generate fields for the current struct level    
    for key, value in struct_data.items():
        selected_rows = df[yaml_key == key]

        if len(selected_rows) > 1:
            go_var = selected_rows['go_var'].values[1]
            toml_key = selected_rows['toml_key'].values[1]
            go_type=selected_rows['go_type'].values[1]
            json_key=selected_rows['json_key'].values[1]
        else:
            go_var = selected_rows['go_var'].values[0]
            toml_key = selected_rows['toml_key'].values[0]
            go_type=selected_rows['go_type'].values[0]
            json_key=selected_rows['json_key'].values[0]

        # add fields to the body of the struct
        struct_string=add_fields_to_struct(struct_string,go_var,go_type,json_key,toml_key)   

    struct_string += "}\n\n"
    
    # recursive case: generate struct definitions for nested structs
    for key, value in struct_data.items():
        selected_rows = df[yaml_key == key]

        if len(selected_rows) > 1:
            go_var = selected_rows['go_var'].values[1]
        else:
            go_var = selected_rows['go_var'].values[0]

        if isinstance(value, dict) and any(isinstance(v, dict) for v in value.values()):
            nested_struct_name = go_var
            nested_struct_data = value
            struct_string += generate_go_struct(nested_struct_name, nested_struct_data)
    
    return struct_string

# read excel
csv_file = "~/downloads/my_configs.csv"
df = pd.read_csv(csv_file)

# remove rows where all columns are nan
df = df.dropna(how='all')
# create the 'json_key' column using the custom function
df['json_key'] = df['yaml_key'].apply(extract_json_key)

data=df['yaml_key'].values.tolist() # read the 'yaml_key' column
data = pd.dataframe({'column':data}) # convert to dataframe

data=data['column'].str.split('.', expand=true) # split by '.'

nested_list = data.values.tolist() # convert to nested list
data=nested_list 

result_json = convert_to_dict(data) # convert to dict (json)

# the generated co code
go_struct = generate_go_struct("", result_json)

# write to file
file_path = "output.go"
with open(file_path, "w") as file:
    file.write(go_struct)
Copier après la connexion

Le problème est (voir ci-dessous une partie du csv),

authentication.authenticator.basic
authentication.authenticator.basic.parameters
authentication.authenticator.basic.parameters.showAuthFailureReason
authentication.authenticator.basic.parameters.showAuthFailureReasonOnLoginPage
authentication.authenticator.totp
authentication.authenticator.totp.parameters
authentication.authenticator.totp.parameters.showAuthFailureReason
authentication.authenticator.totp.parameters.showAuthFailureReasonOnLoginPage
authentication.authenticator.totp.parameters.encodingMethod
authentication.authenticator.totp.parameters.timeStepSize
Copier après la connexion

Ici, puisqu'il y a beaucoup de mots similaires répétés dans la colonne basictotp 字段 parameters 重复,因此脚本会混淆自身并生成两个 totpparameters 结构。预期结果是具有 basicparameterstotpparameters 结构。 csv 的 yaml_key.

Je sais que cela a à voir avec le fait que l'index est codé en dur à 1 dans go_var = selected_rows['go_var'].values[1] mais il est difficile de résoudre ce problème.

Quelqu'un peut-il m'indiquer une réponse ? Je pense,

  1. Problèmes avec les fonctions récursives
  2. Il y a un problème avec le code qui génère json peut être la cause première de ce problème.

Merci !

J'ai également essayé d'utiliser chatgpt, mais comme cela concerne l'imbrication et la récursivité, la réponse fournie par chatgpt n'est pas très efficace.

Mise à jour

J'ai trouvé des doublons dans les colonnes contenant propertiespooloptionsendpointparameters 字段的行存在问题。这是因为它们在 yaml_key.

Solution

J'ai pu résoudre ce problème. Cependant, j'ai dû utiliser une approche complètement nouvelle du problème, qui consistait à utiliser une structure de données arborescente, puis à la parcourir. C'est la logique principale derrière cela - https://www.geeksforgeeks.org/level-sequential tree traversal/

Voici le code python fonctionnel.

import pandas as pd
from collections import deque

structs=[]
class TreeNode:
    def __init__(self, name):
        self.name = name
        self.children = []
        self.path=""

    def add_child(self, child):
        self.children.append(child)

def create_tree(data):
    root = TreeNode('')
    for item in data:
        node = root
        for name in item.split('.'):
            existing_child = next((child for child in node.children if child.name == name), None)
            if existing_child:
                node = existing_child
            else:
                new_child = TreeNode(name)
                node.add_child(new_child)
                node = new_child
    return root

def generate_go_struct(struct_data):
    struct_name = struct_data['struct_name']
    fields = struct_data['fields']
    
    go_struct = f"type {struct_name} struct {{\n"

    for field in fields:
        field_name = field['name']
        field_type = field['type']
        field_default_val = str(field['default_val'])
        json_key=field['json_key']
        toml_key=field['toml_key']

        tail_part=f"\t{field_name} {field_type} `json:\"{json_key},omitempty\" toml:\"{toml_key}\"`\n\n"

        if pd.isna(field['default_val']):
            go_struct += tail_part
        else:
            field_default_val = "\t// +kubebuilder:default:=" + field_default_val
            go_struct += field_default_val + "\n" + tail_part

    go_struct += "}\n\n"
    return go_struct

def write_go_file(go_structs, file_path):
    with open(file_path, 'w') as file:
        for go_struct in go_structs:
            file.write(go_struct)

def create_new_struct(struct_name):
    struct_name = "Configurations" if struct_name == "" else struct_name
    struct_dict = {
        "struct_name": struct_name,
        "fields": []
    }
    
    return struct_dict

def add_field(struct_dict, field_name, field_type,default_val,json_key, toml_key):
    field_dict = {
        "name": field_name,
        "type": field_type,
        "default_val": default_val,
        "json_key":json_key,
        "toml_key":toml_key
    }
    struct_dict["fields"].append(field_dict)
    
    return struct_dict

def traverse_tree(root):
    queue = deque([root])  
    while queue:
        node = queue.popleft()
        filtered_df = df[df['yaml_key'] == node.path]
        go_var = filtered_df['go_var'].values[0] if not filtered_df.empty else None
        go_type = filtered_df['go_type'].values[0] if not filtered_df.empty else None

        if node.path=="":
            go_type="Configurations"

        # The structs themselves
        current_struct = create_new_struct(go_type)
        
        for child in node.children:  
            if (node.name!=""):
                child.path=node.path+"."+child.name   
            else:
                child.path=child.name

            filtered_df = df[df['yaml_key'] == child.path]
            go_var = filtered_df['go_var'].values[0] if not filtered_df.empty else None
            go_type = filtered_df['go_type'].values[0] if not filtered_df.empty else None
            default_val = filtered_df['default_val'].values[0] if not filtered_df.empty else None

            # Struct fields
            json_key = filtered_df['yaml_key'].values[0].split('.')[-1] if not filtered_df.empty else None
            toml_key = filtered_df['toml_key'].values[0].split('.')[-1] if not filtered_df.empty else None
            
            current_struct = add_field(current_struct, go_var, go_type,default_val,json_key, toml_key)

            if (child.children):
                # Add each child to the queue for processing
                queue.append(child)

        go_struct = generate_go_struct(current_struct)
        # print(go_struct,"\n")        
        structs.append(go_struct)

    write_go_file(structs, "output.go")

csv_file = "~/Downloads/my_configs.csv"
df = pd.read_csv(csv_file) 

sample_data=df['yaml_key'].values.tolist()

# Create the tree
tree = create_tree(sample_data)

# Traverse the tree
traverse_tree(tree)

Copier après la connexion

Merci beaucoup pour votre aide !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Quelles bibliothèques sont utilisées pour les opérations du numéro de point flottantes en Go? Quelles bibliothèques sont utilisées pour les opérations du numéro de point flottantes en Go? Apr 02, 2025 pm 02:06 PM

La bibliothèque utilisée pour le fonctionnement du numéro de point flottante dans le langage go présente comment s'assurer que la précision est ...

Quel est le problème avec le fil de file d'attente dans GO's Crawler Colly? Quel est le problème avec le fil de file d'attente dans GO's Crawler Colly? Apr 02, 2025 pm 02:09 PM

Problème de threading de file d'attente dans Go Crawler Colly explore le problème de l'utilisation de la bibliothèque Crawler Crawler dans le langage Go, les développeurs rencontrent souvent des problèmes avec les threads et les files d'attente de demande. � ...

Dans Go, pourquoi les chaînes d'impression avec println et string () ont-elles des effets différents? Dans Go, pourquoi les chaînes d'impression avec println et string () ont-elles des effets différents? Apr 02, 2025 pm 02:03 PM

La différence entre l'impression de chaîne dans le langage go: la différence dans l'effet de l'utilisation de fonctions println et string () est en Go ...

Comment résoudre le problème de conversion de type user_id lors de l'utilisation du flux redis pour implémenter les files d'attente de messages dans le langage Go? Comment résoudre le problème de conversion de type user_id lors de l'utilisation du flux redis pour implémenter les files d'attente de messages dans le langage Go? Apr 02, 2025 pm 04:54 PM

Le problème de l'utilisation de Redessstream pour implémenter les files d'attente de messages dans le langage GO consiste à utiliser le langage GO et redis ...

Quelle est la différence entre la structure de définition des mots clés `var` et« type »dans le langage Go? Quelle est la différence entre la structure de définition des mots clés `var` et« type »dans le langage Go? Apr 02, 2025 pm 12:57 PM

Deux façons de définir les structures dans le langage GO: la différence entre les mots clés VAR et le type. Lorsque vous définissez des structures, GO Language voit souvent deux façons d'écrire différentes: d'abord ...

Quelles bibliothèques de GO sont développées par de grandes entreprises ou fournies par des projets open source bien connus? Quelles bibliothèques de GO sont développées par de grandes entreprises ou fournies par des projets open source bien connus? Apr 02, 2025 pm 04:12 PM

Quelles bibliothèques de GO sont développées par de grandes entreprises ou des projets open source bien connus? Lors de la programmation en Go, les développeurs rencontrent souvent des besoins communs, ...

Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Apr 02, 2025 pm 05:09 PM

Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Lorsque vous utilisez Goland pour le développement du langage GO, de nombreux développeurs rencontreront des balises de structure personnalisées ...

Lorsque vous utilisez SQL.Open, pourquoi ne signale pas une erreur lorsque DSN passe vide? Lorsque vous utilisez SQL.Open, pourquoi ne signale pas une erreur lorsque DSN passe vide? Apr 02, 2025 pm 12:54 PM

Lorsque vous utilisez SQL.Open, pourquoi le DSN ne signale-t-il pas une erreur? En langue go, sql.open ...

See all articles