Лучший способ сгруппировать две структуры в третью на ходу - PullRequest
0 голосов
/ 21 октября 2019

У меня есть следующие структуры:

type A1 struct {
   IdA1 string
   NameA1 string
   key string
}

type B1 struct {
   IdB1 string
   NameB1 string
   Size string
   key string
}

type C1 struct {
   IdA1 string
   Name string
   B1Set B1
}

, и мне нужно создать структуру [] типа C1, которая содержит B1Set из B1, B1 огромнее, чем 2K записей, а A1 - всего 10записей, действительно медленной и неэффективной реализацией было бы перебрать A1 и спросить, равен ли ключ B1 ключу A1, и сохранить на карте результат, но ... есть ли лучший способ реализовать это?

Заранее спасибо,

Добавить дополнительную информацию:

Это два разных файла JSON:

Json1:
[
  {
    "id": "device1",
    "name": "dev1",
    "pool": "pool1"
  },
  {
    "id": "device2",
    "name": "dev2",
    "pool": "pool2"
  }
  ...
]

И другой Json:

[
  {
    "name": "port1",
    "size": 10,
    "pool": "pool1",
    "status": "active"
  },
  {
    "name": "port2",
    "size": 60,
    "pool": "pool1",
    "status": "active"
  },
  {
    "name": "port3",
    "size": 20,
    "pool": "pool2",
    "status": "down"
  },
  {
    "name": "port8",
    "size": 100,
    "pool": "pool2",
    "status": "active"
  },
  {
    "name": "port10",
    "size": 8000,
    "pool": "pool1",
    "status": "active"
  },
  ...
]

Поэтому мне нужно создать новый файл JSON из этих двух файлов со следующим:

[
  {
    "id": "device1",
    "name": "dev1",
    "pool": "pool1",
    "ports": [
         {
           "name": "port1",
           "size": 10,
           "pool": "pool1",
           "status": "active"
         },
         {
           "name": "port2",
           "size": 60,
           "pool": "pool1",
           "status": "active"
         },
         {
           "name": "port10",
           "size": 8000,
           "pool": "pool1",
           "status": "active"
         }
     ]
  },
  {
    "id": "device2",
    "name": "dev2",
    "pool": "pool2",
    "ports": [
         {
           "name": "port3",
           "size": 20,
           "pool": "pool2",
           "status": "active"
         },
         {
           "name": "port8",
           "size": 100,
           "pool": "pool2",
           "status": "active"
         }
     ]
  }
]

, учитывая, что Json1 не более 10-12 записей, а Json2 содержит более 800-1000 записей.

Пока что:

считывает Json1 (устройства) и Json2 (порты) и передает их в две [] структуры. Тогда:

results := make(map[string]*models.PortDevices}
portDevs := []models.PortDevices{}

for i := range devices {
   results[devices[i].Pool] = &models.PortDevices{}
   m := results[devices[i].Pool]
   m.Id = devices[i].Id
   m.Name = devices[i].Name
   m.Pool = devices[i].Pool
   m.Status = devices[i].Status
   for p := range ports {
      if val, ok := results[ports[p].Pool]; ok {
         m := val
         m.Ports = ports
      }
   }

   portDevs = append(portDevs, *m)
}

devports := []models.PortDevices{}

for _, value := range results {
   devports = append(devports, *value)
}

1 Ответ

0 голосов
/ 22 октября 2019

Это то, что вы хотите сделать? https://play.golang.org/p/AZNzQAwRhN0

Для этого создается карта, объединяющая все порты по пулу. Затем он перебирает то, что я назвал clusters, и назначает срез Port соответствующему Cluster, захватывая соответствующий срез на значение Pool.

package main

import (
    "encoding/json"
    "fmt"
)

type Cluster struct {
    ID    string `json:"id"`
    Name  string `json:"name"`
    Pool  string `json:"pool"`
    Ports []Port `json:"ports"`
}

type Port struct {
    Name   string `json:"name"`
    Size   int    `json:"size"`
    Pool   string `json:"pool"`
    Status string `json:"status"`
}

func main() {
    var resources []Port
    err := json.Unmarshal([]byte(resourceJSON), &resources)
    if err != nil {
        panic(err)
    }
    resourcesByPool := make(map[string][]Port)
    for _, resource := range resources {
        if _, ok := resourcesByPool[resource.Pool]; !ok {
            resourcesByPool[resource.Pool] = []Port{}
        }
        resourcesByPool[resource.Pool] = append(resourcesByPool[resource.Pool], resource)
    }

    var clusters []Cluster
    err = json.Unmarshal([]byte(clusterJSON), &clusters)
    if err != nil {
        panic(err)
    }
    for i := 0; i < len(clusters); i++ {
        clusters[i].Ports = resourcesByPool[clusters[i].Pool]
    }

    out, err := json.MarshalIndent(clusters, "", "    ")
    if err != nil {
        panic(err)
    }

    fmt.Println(string(out))

}

var (
    clusterJSON = `[
  {
    "id": "device1",
    "name": "dev1",
    "pool": "pool1"
  },
  {
    "id": "device2",
    "name": "dev2",
    "pool": "pool2"
  }
]`

    resourceJSON = `[
  {
    "name": "port1",
    "size": 10,
    "pool": "pool1",
    "status": "active"
  },
  {
    "name": "port2",
    "size": 60,
    "pool": "pool1",
    "status": "active"
  },
  {
    "name": "port3",
    "size": 20,
    "pool": "pool2",
    "status": "down"
  },
  {
    "name": "port8",
    "size": 100,
    "pool": "pool2",
    "status": "active"
  },
  {
    "name": "port10",
    "size": 8000,
    "pool": "pool1",
    "status": "active"
  }]`
)
...