为了账号安全,请及时绑定邮箱和手机立即绑定

将数据从数据库转换为一个地图

将数据从数据库转换为一个地图

Go
海绵宝宝撒 2022-08-09 16:53:38
问题是 - 我不想为每个数据库创建一个结构(如果我描述所有XL的所有结构,则代码太多,我有超过200个DB)。所以我需要可用于其中任何一个的smth我的一个数据库的数据如下所示:----------------------------------------------Id  |      Path                          |Value-----------------------------------------------1   | SalesPlan/SalesPlanData/Year       | 20212   | SalesPlan/SalesPlanData/Month      | July3   | SalesPlan/SalesPlanPerson/id       | 123....1700| SalesPlan/SalesPlarSpot/Spots/City | NY我尝试了很多方法,但最终,我无法创建一个灵活的映射结构,可以在每个DB行之后正确更新下一个代码允许我存储所有最终标签,但我想在树上向上移动并更新孔结构type ParentTag struct {    Key   string    Value []InnerTag}type InnerTag struct {    Key   string    Value string}func (s *ParentTag) Add(i InnerTag) {    s.Value = append(s.Value, i)    log.Printf("New X=%d", s.Value)}func main() {    //xmlMap := Tag{}    parentTagsStorage := []ParentTag{}    house_1 := []string{"mydoc", "Country", "City", "Street", "House", "14"}    house_2 := []string{"mydoc", "Country", "City", "Street", "House", "15"}    street_1 := []string{"mydoc", "Country", "City", "Street", "Maddison"}    city_1 := []string{"mydoc", "Country", "City", "NY"}    allData := make([][]string, 0)    allData = append(allData, house_1)    allData = append(allData, house_2)    allData = append(allData, street_1)    allData = append(allData, city_1)    for _, row := range allData {        // the latest 2 elements present xml-tag and all previous ones are parents tags        // <Street>        //    <House>1</House>        // </Street>        innerTag := InnerTag{            Key:   row[len(row)-2],            Value: row[len(row)-1],        }        ifParentTagExist := false        for i, pTag := range parentTagsStorage {            if pTag.Key == row[len(row)-3] {                pTag.Add(innerTag)                parentTagsStorage[i] = pTag                ifParentTagExist = true            }        }}对于任何想法,我将非常高兴
查看完整描述

1 回答

?
莫回无

TA贡献1865条经验 获得超7个赞

好了,我们开始吧:


package main


import (

    "encoding/json"

    "encoding/xml"

    "fmt"

    "io"

    "os"

    "strings"

)


type pathVal struct {

    path string

    val  interface{}

}


func encode(dst io.Writer, src []pathVal) error {

    enc := xml.NewEncoder(dst)

    enc.Indent("", "\t") // for a prettier look


    tree := makeTree(src)


    err := encodeTree(enc, tree)

    if err != nil {

        return err

    }


    return enc.Flush()

}


func encodeTree(enc *xml.Encoder, tree tree) error {

    for key, node := range tree {

        err := enc.EncodeToken(xml.StartElement{

            Name: xml.Name{

                Local: key,

            },

        })

        if err != nil {

            return err

        }


        if node.SubTree != nil {

            err = encodeTree(enc, node.SubTree)

            if err != nil {

                return err

            }

        }

        if node.Value != nil {

            err = encodeValue(enc, node.Value)

            if err != nil {

                return err

            }

        }


        err = enc.EncodeToken(xml.EndElement{

            Name: xml.Name{

                Local: key,

            },

        })

        if err != nil {

            return err

        }

    }


    return nil

}


func encodeValue(enc *xml.Encoder, val interface{}) error {

    return enc.EncodeToken(xml.CharData(fmt.Sprintf("%v", val)))

}


type tree map[string]*treeNode


type treeNode struct {

    SubTree tree

    Value   interface{}

}


func makeTree(src []pathVal) tree {

    root := make(tree)


    for _, elem := range src {

        comps := strings.Split(elem.path, "/")

        comps, last := comps[:len(comps)-1], comps[len(comps)-1]


        subTree := root

        for _, comp := range comps {

            node, exists := subTree[comp]

            if !exists {

                newTree := make(tree)

                subTree[comp] = &treeNode{

                    SubTree: newTree,

                }

                subTree = newTree

                continue

            }

            if node.SubTree == nil {

                node.SubTree = make(tree)

            }

            subTree = node.SubTree

        }


        if node, exists := subTree[last]; exists {

            node.Value = elem.val

        } else {

            subTree[last] = &treeNode{

                Value: elem.val,

            }

        }

    }


    return root

}


// "Table 1"

var data1 = []pathVal{

    pathVal{

        path: "SalesPlan/SalesPlanData/Year",

        val:  2021,

    },

    pathVal{

        path: "SalesPlan/SalesPlanData/Month",

        val:  "July",

    },

    pathVal{

        path: "SalesPlan/SalesPlanData/id",

        val:  123,

    },

    pathVal{

        path: "SalesPlan/SalesPlanSpot/Spots/City",

        val:  "NY",

    },

}


// "Table 2"

var data2 = []pathVal{

    pathVal{

        path: "mydoc/Country/City/Street/House",

        val:  14,

    },

    pathVal{

        path: "mydoc/Country/City/Street/House",

        val:  15,

    },

    pathVal{

        path: "mydoc/Country/City/Street",

        val:  "Maddison",

    },

    pathVal{

        path: "mydoc/Country/City",

        val:  "NY",

    },

}


func main() {

    out, _ := json.MarshalIndent(makeTree(data1), "", "\t")

    fmt.Printf("%s\n", out)

    fmt.Println(encode(os.Stdout, data1))


    out, _ = json.MarshalIndent(makeTree(data2), "", "\t")

    fmt.Printf("%s\n", out)

    fmt.Println(encode(os.Stdout, data2))

}

(游乐场。


在示例数据(嵌入到示例中的两个“表”)上,我们得到data1data2


<SalesPlan>

    <SalesPlanData>

        <id>123</id>

        <Year>2021</Year>

        <Month>July</Month>

    </SalesPlanData>

    <SalesPlanSpot>

        <Spots>

            <City>NY</City>

        </Spots>

    </SalesPlanSpot>

</SalesPlan>


<mydoc>

    <Country>

        <City>

            <Street>

                <House>15</House>Maddison

            </Street>NY

        </City>

    </Country>

</mydoc>

分别。


注意那些“看起来很奇怪”的情况,“麦迪逊”放在元素里面,“NY”放在元素里面;还要注意 .

我不知道如何处理这两个问题(如果它们是问题),因为你的问题没有明确说明任何关于处理它们的偏好。<Street><City><House>14</House>


我会说处理多个叶元素是相当容易的 - 只需确保不覆盖 中,而是提供收集多个值(可能收集在切片中)并在 中说明这一点。

如何处理一个潜在的XML元素,它应该同时包含一个“普通”值和一个嵌套元素,这实际上是一个悬而未决的问题:我所展示的是100%符合标准的XML,但最终结果可能会让人觉得不自然,因为人们通常期望在人类可读的XML文档中看到的内容。ValuemakeTreeencodeTree


不过,让我把这些作为读者的练习。


请注意,该解决方案仅使用包来“转储”从输入数据创建的树;它不需要算法工作。


查看完整回答
反对 回复 2022-08-09
  • 1 回答
  • 0 关注
  • 107 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信