github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/types/map2table.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "reflect" 6 "sort" 7 ) 8 9 func MapToTable(v []interface{}, callback func([]string) error) error { 10 if len(v) == 0 { 11 return nil 12 } 13 14 if reflect.TypeOf(v[0]).Kind() != reflect.Map { 15 return fmt.Errorf("expecting map on row %d, instead got a %s", 0, reflect.TypeOf(v[0]).Kind().String()) 16 } 17 18 headings, err := getMapKeys(v[0].(map[string]any)) 19 if err != nil { 20 return err 21 } 22 23 //table := make([][]string, len(v)+1) 24 //table[0] = headings 25 err = callback(headings) 26 if err != nil { 27 return err 28 } 29 30 lenHeadings := len(headings) 31 slice := make([]string, lenHeadings) 32 var j int 33 34 for i := range v { 35 //if reflect.TypeOf(v[i]).Kind() != reflect.Map { 36 // return nil, fmt.Errorf("expecting map on row %d, instead got a %s", i, reflect.TypeOf(v[i]).Kind().String()) 37 //} 38 39 m, ok := v[i].(map[string]any) 40 if !ok { 41 return fmt.Errorf("expecting map on row %d, instead got a %s", i, reflect.TypeOf(v[i]).Kind().String()) 42 } 43 44 if len(m) != len(headings) { 45 return fmt.Errorf("row %d has a different number of records to the first row:\nrow 0 == %d records,\nrow %d == %d records", 46 i, lenHeadings, i, len(v)) 47 } 48 49 for j = 0; j < lenHeadings; j++ { 50 val, ok := v[i].(map[string]any)[headings[j]] 51 if !ok { 52 return fmt.Errorf("row %d is missing a record name found in the first row: '%s'", i, headings[j]) 53 } 54 s, err := ConvertGoType(val, String) 55 if err != nil { 56 return fmt.Errorf("cannot convert a %T (%v) to a %s in record %d: %s", val, val, String, i, err.Error()) 57 } 58 slice[j] = s.(string) 59 } 60 61 err = callback(slice) 62 if err != nil { 63 return err 64 } 65 } 66 67 return nil 68 } 69 70 func getMapKeys(v map[string]any) ([]string, error) { 71 slice := make([]string, len(v)) 72 var i int 73 74 for k := range v { 75 s, err := ConvertGoType(k, String) 76 if err != nil { 77 return nil, fmt.Errorf("cannot convert a %T (%v) to a %s: %s", k, k, String, err.Error()) 78 } 79 slice[i] = s.(string) 80 i++ 81 } 82 sort.Strings(slice) 83 return slice, nil 84 }