V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
olddogs
V2EX  ›  Go 编程语言

go 语言,如何实现这样的嵌套循环?

  •  
  •   olddogs · 2022-05-25 19:05:50 +08:00 · 3385 次点击
    这是一个创建于 930 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请问在数据库里面查询出来的列表,如何循环出这样的分组结构呢?

    "manage": {
       "ent": {
       "export": true,
       "get": true,
       "plan": true
      }
    },
    "oa": {
       "user": {
         "add": true,
         "addDept": true,
         "addUser": true,
         "get": true,
         "plan": true
      }
    }
    

    用 php 可以通过循环,这样拼接,但是用 go 就玩不好了

    $newList[$v['name']][$v1['name']][$v2['name']] = true
    

    感谢!

    第 1 条附言  ·  2022-05-25 19:50:09 +08:00

    类似这样的数据 ,

    {
      "id": 1,
      "name": "manage",
      "parent_id": 0,
      "children": [
        {
          "id": 101,
          "name": "ent",
          "parent_id": 1,
          "children": [
            {
              "id": 102,
              "name": "get",
              "parent_id": 101
            },
            {
              "id": 103,
              "name": "edit",
              "parent_id": 101
            }
          ]
        }
      ]
    }
    
    

    我现在的写法,但是这样有问题,这样没办法按照children分组,麻烦帮忙看看

    
    func ruleListToObj(rules []Rule) (list map[string]map[string]map[string]bool) {
    	root := make(map[string]map[string]map[string]bool)
    	module := make(map[string]map[string]bool)
    	view := make(map[string]bool)
    
    	for _, v := range rules {
    		root[v.Name] = module
    		if len(v.Children) > 0 {
    			for _, vv := range v.Children {
    				module[vv.Name] = view
    				if len(vv.Children) > 0 {
    					for _, vvv := range v.Children {
    						view[vvv.Name] = true
    					}
    				}
    			}
    		}
    	}
    	return root
    }
    
    第 2 条附言  ·  2022-05-27 15:59:40 +08:00

    其实我就是要把数据库查出来的list,压成下面这样key value 的形式输出

    
    {
      "data": {
        "manage": {
          "ent": {
            "get": true,
            "edit": true
          },
          "app": {
            "get": true,
            "edit": true
          },
          "dept": {
            "get": true,
            "addDept": true,
            "editDept": true,
            "delDept": true,
            "addUser": true,
            "editUser": true,
            "statusUser": true
          },
          "role": {
            "get": true,
            "add": true,
            "edit": true,
            "editAuth": true,
            "del": true
          },
          "crm": {
            "get": true
          },
          "log": {
            "get": true
          },
          "setting": {
            "get": true
          }
        },
        "oa": {
          "daily": {
            "get": true
          },
          "schedule": {
            "get": true
          },
          "examine": {
            "get": true
          },
          "book": {
            "get": true
          }
        },
        "bi": {
          "datas": {
            "get": true
          },
          "visit": {
            "get": true
          }
        }
      }
    }
    
    
    45 条回复    2022-05-28 13:39:15 +08:00
    iamzuoxinyu
        1
    iamzuoxinyu  
       2022-05-25 19:22:02 +08:00
    OP 表述能力堪忧……你这代码既看不出来有什么分组也看不出来有什么循环。
    lizhien
        2
    lizhien  
       2022-05-25 19:39:08 +08:00
    不知道你想说啥,不过下面的赋值用 map 不是就可以做到吗?
    olddogs
        3
    olddogs  
    OP
       2022-05-25 19:51:18 +08:00
    @iamzuoxinyu
    @lizhien

    抱歉啊,我确实没表述清楚,现在我又补了一点信息
    dcalsky
        4
    dcalsky  
       2022-05-25 20:15:19 +08:00
    要先定义 struct 数据结构再解析,一直用 hashmap 可不是什么好习惯。
    olddogs
        5
    olddogs  
    OP
       2022-05-25 20:29:04 +08:00
    @dcalsky 额,多谢啊。请问能帮忙解决一下我的问题吗?
    WintersZhang
        6
    WintersZhang  
       2022-05-25 20:38:47 +08:00
    相对复杂的结构不是特别适合用 map 来解析吧,实现定义好要解析的 json 相对应的 struct ,然后直接用 json 包的 Unmarshal 就可以了,类似这样:

    text := [你要解析的数据]

    type entry struct {
    Id int `json:"id"`
    Name string `json:"name"`
    ParentId int `json:"parent_id"`
    Children []entry `json:"children"`
    }
    e := entry{}
    json.Unmarshal([]byte(text), &e)
    WintersZhang
        7
    WintersZhang  
       2022-05-25 20:40:51 +08:00
    emmm ,才注册不久,评论不能用 markdown ,tab 缩进也会被吃掉么...
    代码片段 OP 凑合看看吧
    seers
        8
    seers  
       2022-05-25 20:41:22 +08:00
    定义一个 children struct ,然后使用 children 数组
    olddogs
        9
    olddogs  
    OP
       2022-05-25 20:50:41 +08:00
    @WintersZhang
    @seers
    我想实现的是最上面的那个结构
    "manage": {
    "ent": {
    "export": true,
    "get": true,
    "plan": true
    }
    },
    WintersZhang
        10
    WintersZhang  
       2022-05-25 20:55:40 +08:00
    @olddogs
    php 不太懂。。
    go 的话,我觉得是一样的道理啊,把要解析的字段都定义到 struct 里,然后直接解析
    olddogs
        11
    olddogs  
    OP
       2022-05-25 21:05:44 +08:00
    @WintersZhang 试了好久,就是不行,能帮忙研究一下嘛,多谢拉
    LoNeFong
        12
    LoNeFong  
       2022-05-25 21:05:51 +08:00
    看起来就是一个链表
    iamzuoxinyu
        13
    iamzuoxinyu  
       2022-05-25 21:45:36 +08:00
    这是树状结构吧……什么奇葩设计。你是想把树状拍平么?
    6IbA2bj5ip3tK49j
        14
    6IbA2bj5ip3tK49j  
       2022-05-25 21:50:18 +08:00
    哈哈,crud ,集合操作,大道至简在这儿就不太管用了。
    olddogs
        15
    olddogs  
    OP
       2022-05-25 21:52:22 +08:00
    @iamzuoxinyu 是的,就是打算把树状拍平,有咩有办法啊? 大佬
    iamzuoxinyu
        16
    iamzuoxinyu  
       2022-05-25 21:54:10 +08:00
    @olddogs 都树状了,那就递归啊……另外我不知道你的 json 数据是谁,怎么提供的,要我就喷死设计这个接口的人。
    olddogs
        17
    olddogs  
    OP
       2022-05-25 21:57:26 +08:00
    @iamzuoxinyu 是啊,我现在就是递归,问题是,水平有限,递归不到拍平的样子 o(╥﹏╥)o
    iamzuoxinyu
        18
    iamzuoxinyu  
       2022-05-25 22:04:30 +08:00
    首先,按照 @WintersZhang 给出的结构反序列化。

    ```go
    func flatten(ent *entry) []*entry {
    entries := make([]*entry, 0)
    entries = append(entries, ent)
    if len(ent.children) > 0 {
    entries = append(entries, flatten(ent.children)...)
    }
    return entries
    }
    ```

    建议补一下数据结构……
    iamzuoxinyu
        19
    iamzuoxinyu  
       2022-05-25 22:06:32 +08:00
    @iamzuoxinyu
    ```go
    func flatten(ent *entry) []*entry {
    entries := make([]*entry, 0)
    entries = append(entries, ent)
    for child := range ent.children {
    entries = append(entries, flatten(child)...)
    }
    return entries
    }
    ```
    iamzuoxinyu
        20
    iamzuoxinyu  
       2022-05-25 22:07:41 +08:00
    草,v2ex 的 markdown 机制好迷。
    choury
        21
    choury  
       2022-05-25 22:25:15 +08:00
    定义一个结构
    struct Child{
    Id int `json:"id"`
    Name string `json:"name"`
    ParentId int `json:"parent_id"`
    Children json.RawMessage `json:"children"`
    }

    把结果发序列化之后,把 child.Children 字段继续递归反序列化,最后存到一个数组就行了
    olddogs
        22
    olddogs  
    OP
       2022-05-25 22:34:18 +08:00
    @iamzuoxinyu 可能理解错了吧,我是要拍平成类似链表的感觉
    iamzuoxinyu
        23
    iamzuoxinyu  
       2022-05-25 22:36:53 +08:00
    @olddogs 树状怎么可能变成链表。
    olddogs
        24
    olddogs  
    OP
       2022-05-25 22:42:17 +08:00
    @iamzuoxinyu o(╥﹏╥)o ,好吧,看来我只能换个思路了,哎,多谢了
    playniuniu
        25
    playniuniu  
       2022-05-25 23:50:50 +08:00
    完全没看明白想干啥,如果是想动态解析 json 文件,然后取得里面一些值的话,试试 gjson

    https://github.com/tidwall/gjson
    GeruzoniAnsasu
        26
    GeruzoniAnsasu  
       2022-05-26 07:20:27 +08:00
    你写的是 list 转 map

    然后你问 map 压平怎么压




    你真的搞清楚你想问什么了????


    这个看不懂的话就没人能帮你了
    https://go.dev/play/p/oje5ib9Pu-n
    cnbattle
        27
    cnbattle  
       2022-05-26 08:19:30 +08:00 via Android
    List 的 key index 拼接处理成 map 的 key?
    GeruzoniAnsasu
        28
    GeruzoniAnsasu  
       2022-05-26 08:36:07 +08:00
    1a7489
        29
    1a7489  
       2022-05-26 10:14:13 +08:00
    用 go 把 json 发送给 php 处理完了在返回 json🤣🤣🤣
    MoYi123
        30
    MoYi123  
       2022-05-26 10:51:38 +08:00
    能给个输入+对应的输出吗?
    给了 2 个例子, 一个没输入, 一个没期望输出.

    要操作树, 你肯定要会 bfs 和 dfs, 这 2 个不理解, 代码肯定不会写.
    tbxark
        31
    tbxark  
       2022-05-26 19:06:10 +08:00
    用这个 https://github.com/tidwall/gjson, 你的意思应该是根据 keypath 获取 value 吧
    ```go
    package main

    import "github.com/tidwall/gjson"

    const json = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`

    func main() {
    value := gjson.Get(json, "name.last")
    println(value.String())
    }
    ```
    olddogs
        32
    olddogs  
    OP
       2022-05-27 15:49:42 +08:00
    @playniuniu 不是想解析 json ,我贴 json ,是为了给看结构
    olddogs
        33
    olddogs  
    OP
       2022-05-27 15:52:19 +08:00
    @GeruzoniAnsasu 不是啊,其实我就是要把 sql 查出来的 List ,里面 的 key index 拼接处理成 map 的 key
    GeruzoniAnsasu
        34
    GeruzoniAnsasu  
       2022-05-27 16:28:41 +08:00
    @olddogs 你贴了 4 次代码都没解释清楚源结构是什么目标结构是什么,我真的服气。

    #15
    > 是的,就是打算把树状拍平,有咩有办法啊? 大佬

    查询出来的 list 是平坦的,你到底要从 k-v list 拼出一个树还是要把深度>1 的树平坦化成 k-v list ,至今是矛盾的。



    你给了这么多示例的 json ,全完全不提表结构是什么,最后一次贴的这有上百个不同单词的 json ,你想让别人怎么心灵感应每个单词 /字段从哪来?




    其实上面这么多回复,有灵性的早都可以想出来了

    1. 并不需要 map[string]map[string] ....,map[string]interface{} 就足够了
    2. children 这种嵌套可以用自引用模型直接在查询时查出一个嵌套的结构体
    3. 你第一条附言给的数据 flatten 的代码给你了,你试了吗
    4. gorm 的文档你好好看了吗,嵌套 preload 你看到了吗
    GeruzoniAnsasu
        35
    GeruzoniAnsasu  
       2022-05-27 16:30:49 +08:00
    你好像不知道你贴的所有 json 都不叫「一个列表」
    lbp0200
        36
    lbp0200  
       2022-05-27 18:58:34 +08:00
    巨婴伸手党,等着别人喂
    olddogs
        37
    olddogs  
    OP
       2022-05-28 13:07:04 +08:00
    @GeruzoniAnsasu 抱歉啊,这几天太忙了,昨天有比较急的事,搞到很晚,目标结构就是我最后一次贴的 json ,其实我现在已经换了一种方法实现了,也就是最后一次贴的代码,只是实现的比较蹩脚,我用 go 输出的树结构,然后我用 vue 拿到数据后,通过 js 的写法实现的!
    olddogs
        38
    olddogs  
    OP
       2022-05-28 13:07:42 +08:00
    @tbxark 不是的,是我最后一次贴的 json ,这个是最终要实现的
    olddogs
        39
    olddogs  
    OP
       2022-05-28 13:09:28 +08:00
    @choury 额,我要的不是一个数组,是最后一次我贴的 json ,非常感谢
    olddogs
        40
    olddogs  
    OP
       2022-05-28 13:10:36 +08:00
    @LoNeFong 类似吧
    olddogs
        41
    olddogs  
    OP
       2022-05-28 13:11:59 +08:00
    @1a7489 我现在就是给树结构到 vue ,然后用 js 处理使用,蹩脚啊!
    olddogs
        42
    olddogs  
    OP
       2022-05-28 13:14:12 +08:00
    @GeruzoniAnsasu 抱歉抱歉,你写的代码我跑了的,还有上面那个老哥的也是,非常感谢能上心我的问题
    olddogs
        43
    olddogs  
    OP
       2022-05-28 13:19:29 +08:00
    @MoYi123 表结构,就是第二个 json ,那个实际上是我已经从库里面查询出来生成的树,
    表就是以 parent_id,id ,这个父子关系来存数据的,要输出的,就是我最后一次贴的 json

    另外多谢提醒,我也是刚上手,go ,哎,抱歉抱歉,添麻烦了!
    olddogs
        44
    olddogs  
    OP
       2022-05-28 13:20:37 +08:00
    @cnbattle 通透,能传授点经验吗,大佬
    olddogs
        45
    olddogs  
    OP
       2022-05-28 13:39:15 +08:00
    @lbp0200 切莫侮辱人格,人都有难处的时候! 换位思考、换位思考,不奢望你大神能解我的难,但还希望你能管住自己的手,🙏🏻
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3001 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 11:02 · PVG 19:02 · LAX 03:02 · JFK 06:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.