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?
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))
}