drlndkhib08556095 2017-06-01 06:14
浏览 63
已采纳

如何在golang中的切片中动态地将对象分配给字符串键?

I am trying to create an array from already created array. Array that I have is

{
  "id": 1,
  "category": "fruits",
  "name": "Apple",
  "description": "Apple is my favorite fruit."
}

{
  "id": 2,
  "category": "colors",
  "name": "Red",
  "description": "Red color is always charming."
}

{
  "id": 3,
  "category": "flowers",
  "name": "Lotus",
  "description": "It is one of the most beautiful flowers in this world."
}

{
  "id": 4,
  "category": "colors",
  "name": "Pink",
  "description": "A romantic color, mostly liked by women."
}
{
  "id": 5,
  "category": "flowers",
  "name": "Rose",
  "description": "I love roses."
}

{
  "id": 6,
  "category": "fruits",
  "name": "Mango",
  "description": "Mango is one of my favorite fruits."
}

Now I need to create an array and populate data like:

"elements":{
   "fruits":{
      0:{
         "id": 1,
         "category": "fruits",
         "name": "Apple",
         "description": "Apple is my favorite fruit."
       }
     1:{
        "id": 6,
        "category": "fruits",
        "name": "Mango",
        "description": "Mango is one of my favorite fruits."
       }
     }
    "flowers":{
        0:{
            "id": 3,
            "category": "flowers",
            "name": "Lotus",
            "description": "It is one of the most beautiful flowers in this world."
         }
        1:{
          "id": 5,
          "category": "flowers",
          "name": "Rose",
          "description": "I love roses."
        }
      }
    "colors":{
       0:{
          "id": 2,
          "category": "colors",
          "name": "Red",
          "description": "Red color is always charming."
        }
      1:{
        "id": 4,
        "category": "colors",
        "name": "Pink",
        "description": "A romantic color, mostly liked by women."
       } 
    }
}

What I have tried is:

    arr             := make(map[string]interface{})
    arrCate         := make(map[string]interface{})
    arrCateFlower   := make(map[int]interface{})
    arrCateColor    := make(map[int]interface{})
    arrCateFruit    := make(map[int]interface{})

    for index, data := range dataVals{
        if(data.Category == "flower"){
            arrCateFlower[index] = data
        }
        if(data.Category == "colors"){
            arrCateColor[index] = data  
        }
        if(data.Category == "fruits"){
            arrCateFruit[index] = data  
        }
    }
    arrCate["flowers"] = arrCateFlower
    arrCate["colors"] = arrCateColor
    arrCate["fruits"] = arrCateFruit
    arr["elements"] = arrCate

Where dataVals contain the unformatted data given at the top. By applying the above code I am able to get the proper output. But I don't think it is efficient way. If I try something like

    arr             := make(map[string]interface{})
    arrCate         := make(map[string]interface{})

    for _, data := range dataVals{
      arrCate[data.Category] = data    
    }
    arr["elements"] = arrCate

Then I get something like:

"elements":{
   "fruits":{
              "id": 6,
              "category": "fruits",
              "name": "Mango",
              "description": "Mango is one of my favorite fruits."
            }
    "flowers":{
               "id": 5,
               "category": "flowers",
               "name": "Rose",
               "description": "I love roses."
              }
    "colors":{
               "id": 4,
               "category": "colors",
               "name": "Pink",
               "description": "A romantic color, mostly liked by women." 
             }
}

the last elements of that particular category in the loop. I don't understand how can I get all the elements in the array without using any static values in code.

I have already spent hours in this. Can anyone please tell what am i missing in it?

  • 写回答

1条回答 默认 最新

  • dongsi4815 2017-06-01 06:53
    关注

    https://play.golang.org/p/y-I6Fb_61R

    I hope you can live with the additional outer {} pair.

    And without the outer {} pair: https://play.golang.org/p/SSTgln0qJc

    To not just have a bunch of links and to enable easy criticism of my solution by others, I include the code here, slightly redacted:

    package main
    
    import (
        "fmt"
        "encoding/json"
        "log"
        "strings"
    )
    
    var dataAsString = `` //put data between the ``
    
    type Item struct {
        Id          int    `json:"id"`
        Category    string `json:"category"`
        Name        string `json:"name"`
        Description string `json:"description"`
    }
    
    type CategoryToItemSliceMap map[string][]Item
    type CategoryToIndexItemMap map[string]map[int]Item
    
    func main() {
        // first read the data, we use a decoder as the input was given
        // as a stream of seperate json objects and not a big single one.
    
        decoder := json.NewDecoder(strings.NewReader(dataAsString))
        var ourData []Item
        for decoder.More() {
            var it Item
            err := decoder.Decode(&it)
            if err != nil {
                log.Fatalln(err)
            }
            ourData = append(ourData, it)
        }
    
        // collect items according to categories
        catToItemSlice := CategoryToItemSliceMap{}
        for _,v := range ourData {
            catToItemSlice[v.Category] = append(catToItemSlice[v.Category],v)
        }
    
        // turn those slices into int -> Item maps so we get the index numbers
        // in the encoded json
        catToIndexItemMap := CategoryToIndexItemMap{}
        for k,v := range catToItemSlice {
            if catToIndexItemMap[k] == nil {
                catToIndexItemMap[k] = map[int]Item{}
            }
            for index, item := range v {
               catToIndexItemMap[k][index] = item
            }
        }
    
        // easiest way to get the "elements: " without an additional outer {} 
        // brace pair
        fmt.Printf("elements: ")
    
        // We only have one json object in the output and that is a map, so we
        // can use Unmarshal and don't need a streaming encoder. And get nice
        // indentation with MarshalIndent.
        out, err := json.MarshalIndent(catToIndexItemMap, "", "    ")
        if err != nil {
            log.Fatalln(err)
        }
        fmt.Println(string(out))
    
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 2024-五一综合模拟赛
  • ¥15 如何将下列的“无限压缩存储器”设计出来
  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口