Go - Divide big.Float - math

I'm dealing with numbers that require a big.Float type, and I need to divide them. I'm aware that big.Int has a .Div() function, but if I'm correct, that truncates the value and loses the precision I get from using big.Float.
Relevant code
func e(prec int64) (res *big.Float) {
res = big.NewFloat(float64(1.0))
base := big.NewInt(prec)
for i := base; i.Cmp(big.NewInt(int64(0))) == 1; _ = i.Sub(i, big.NewInt(1)) {
d := big.NewFloat(float64(1.0))
_ = d.Div(fact(i)) // error here
res.Add(d)
}
return
}

Use Float.Quo for big.Float division:
x, y := big.NewFloat(10), big.NewFloat(3)
z := new(big.Float).Quo(x, y)
http://play.golang.org/p/GRPAKQNkq0

Related

Insert objects in specific order with map

I have a use case where the order of objects needs to be in a specific order. The current implementation is done with using map and I've found numerous posts and articles where it states that map are an unordered list. All of the solutions that I found are those where they've made the keys as integers and they've used sort.Ints(keys) to sort by keys.
In the code, I'm using a yaml template to instantiate a dictionary pair, then passing it into the ProcessFruits function where it does the logic.
How would I go about getting the desired result (see below) where the object from the top of the list in fruits.yml.tmpl will always be first?
Here's a simplified version of my code:
//Filename: fruits.yml.tmpl
fruits: {{ $fruits := processFruits
"oranges" true
"bananas" false
"apples" true
}}
{{ $fruits }}
//Filename: fruits.go
func ProcessFruits(fruits map[string]interface{}) (interface{}) {
keys := make([]string, len(fruits))
i := 0
for fruit := range fruits {
keys[i] = fruit
i++
}
sort.Strings(keys)
fmt.Println(keys)
}
// Connect fruits.yml.tmpl to the ProcessFruits function
tmpl, err := template.New(t).Funcs(template.FuncMap(map[string]interface{}{
"processFruits": ProcessFruits,
})).Funcs(sprig.TxtFuncMap())
Actual Results:
[apples:true bananas:false oranges:true]
Desired Results:
[oranges:true bananas:false apples:true]
Go Playground
https://go.dev/play/p/hK2AdRVsZXJ
You are missing the usage of sort.Reverse() and sort.StringSlice()
func main() {
keys := []string{"bananas", "apples", "oranges"}
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
fmt.Println(keys)
}
https://go.dev/play/p/n08S7xtbeij
See: https://pkg.go.dev/sort#example-Reverse
The arguments are passed as a slice. Collect every other argument as a string and print:
func ProcessFruits(args ...interface{}) interface{} {
var fruits []string
for i, arg := range args {
if i%2 == 0 {
fruits = append(fruits, arg.(string))
}
}
fmt.Println(fruits)
return nil
}
Not the prettiest solution, but I think I've figured out a working code to my problem. What I've done was creating another dictionary that will keep track of the order of the "fruits", then combining the two dictionary together with a nested for loop and output the result to a slice.
Here's my code:
package main
import (
"fmt"
"sort"
)
func ProcessFruits(fruits map[string]interface{}, counts map[int]string) {
keys := make([]string, len(fruits))
var foo []string
var baz []int
for k := range fruits {
foo = append(foo, k)
}
for _, k := range foo {
fmt.Println("Key-string:", k, "Value-bool:", fruits[k])
}
fmt.Println("==========================")
// Iterate over counts (keys are ints)
for l := range counts {
baz = append(baz, l)
}
sort.Ints(baz)
for _, l := range baz {
fmt.Println("Key-int:", l, "Value-string:", counts[l])
}
fmt.Println("==========================")
// Correlate list with sorted integer keys with the other list that contains true/false
i := 0
for _, m := range baz {
for _, n := range foo {
//fmt.Println("Key-int:", m, "Value-string:", counts[m])
//fmt.Println("Key-string:", n, "Value-bool:", fruits[n])
if counts[m] == n {
keys[i] = n
i++
//fmt.Println(i)
}
}
}
// Desired results is now in the slice, keys.
fmt.Println(keys)
}
func main() {
var m = map[string]interface{}{
"oranges": true,
"bananas": false,
"apples": true,
}
var n = map[int]string{
0: "oranges",
1: "bananas",
2: "apples",
}
ProcessFruits(m, n)
}
If anyone has a better solution, then I'd be curious to know.

Check if key exists in multiple maps in one condition

I need to check if the same key exists in two maps:
if v1, ok1 := map1["aaa"]; ok1 {
...
}
if v2, ok2 := map2["aaa"]; ok2 {
...
}
Is it possible to join these two conditions into one? I managed to do something like this:
v1, ok1 := map1["aaa"]
v2, ok2 := map2["aaa"]
if ok1 && ok2 {
...
}
but I'm curious whether it (assigning and checking) can be done in one if condition.
No, it can't be done. Spec: Index expressions:
An index expression on a map a of type map[K]V used in an assignment or initialization of the special form
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
yields an additional untyped boolean value. The value of ok is true if the key x is present in the map, and false otherwise.
So you can use the special v, ok := m[k] form only if nothing else gets assigned.
However, if you don't use the zero value of the value type of the map, you can do the check using a simple tuple-assignment; by not using the special form but 2 simple index expressions.
For example if your value type is some interface type (e.g. interface{}), and you know you don't use the nil value, you may do the following:
if v1, v2 := m1["aaa"], m2["aaa"]; v1 != nil && v2 != nil {
fmt.Printf("Both map contains key '%s': %v, %v\n", "aaa", v1, v2)
}
Of course with a helper function, you can do it in one step:
func idx(m1, m2 map[string]interface{}, k string) (
v1, v2 interface{}, ok1, ok2 bool) {
v1, ok1 = m1[k]
v2, ok2 = m2[k]
return
}
Using it:
if v1, v2, ok1, ok2 := idx(m1, m2, "aaa"); ok1 && ok2 {
fmt.Printf("Both map contains key '%s': %v, %v\n", "aaa", v1, v2)
}
Try the examples on the Go Playground.
you could also use variadic parameter(three dots) to check multiple keys :
// check map 1 and map2 is null or not
func checkMap(m1, m2 map[string]interface{}, keys ...string) []bool {
var isExist []bool
for key := range keys {
//checking value from map 1
_, ok := m1[keys[key]]
if ok {
isExist = append(isExist, true) // append for the first time to avoid panic
} else {
isExist = append(isExist, false) // append for the first time to avoid panic
}
// checking value from map2
_, ok = m2[keys[key]]
if ok {
isExist[key] = true
} else {
isExist[key] = false
}
}
return isExist
}
And then you can check your keys in order like this :
result := checkMap(myMap, myMap2, "a", "b", "c", "d", "e", "f", "g")
fmt.Printf("result = %+v\n", result) // print the result
if result[0] {
fmt.Println("key a exist in both map")
}
if result[1] {
fmt.Println("key b exist in both map")
}

How to convert interface{} to map

I am trying to create a function that could accept following
*struct
[]*struct
map[string]*struct
Here struct could be any struct not just a specific one.
Converting interface to *struct or []*struct is working fine.
But giving error for map.
After reflect it shows it is map[] but giving error when try to iterate over range.
Here is code
package main
import (
"fmt"
"reflect"
)
type Book struct {
ID int
Title string
Year int
}
func process(in interface{}, isSlice bool, isMap bool) {
v := reflect.ValueOf(in)
if isSlice {
for i := 0; i < v.Len(); i++ {
strct := v.Index(i).Interface()
//... proccess struct
}
return
}
if isMap {
fmt.Printf("Type: %v\n", v) // map[]
for _, s := range v { // Error: cannot range over v (type reflect.Value)
fmt.Printf("Value: %v\n", s.Interface())
}
}
}
func main() {
b := Book{}
b.Title = "Learn Go Language"
b.Year = 2014
m := make(map[string]*Book)
m["1"] = &b
process(m, false, true)
}
Is there any way to convert interface{} to map and iterate or get it's elements.
If the map value can be any type, then use reflect to iterate through the map:
if v.Kind() == reflect.Map {
for _, key := range v.MapKeys() {
strct := v.MapIndex(key)
fmt.Println(key.Interface(), strct.Interface())
}
}
playground example
If there's a small and known set of struct types, then a type switch can be used:
func process(in interface{}) {
switch v := in.(type) {
case map[string]*Book:
for s, b := range v {
// b has type *Book
fmt.Printf("%s: book=%v\n" s, b)
}
case map[string]*Author:
for s, a := range v {
// a has type *Author
fmt.Printf("%s: author=%v\n" s, a)
}
case []*Book:
for i, b := range v {
fmt.Printf("%d: book=%v\n" i, b)
}
case []*Author:
for i, a := range v {
fmt.Printf("%d: author=%v\n" i, a)
}
case *Book:
fmt.Ptintf("book=%v\n", v)
case *Author:
fmt.Printf("author=%v\n", v)
default:
// handle unknown type
}
}
You don't need reflect here. Try:
v, ok := in.(map[string]*Book)
if !ok {
// Can't assert, handle error.
}
for _, s := range v {
fmt.Printf("Value: %v\n", s)
}
Same goes for the rest of your function. It looks like you're using reflection when you would be better served by a type switch.
Alternatively, if you insist on using reflection here (which doesn't make a lot of sense) you can also use Value.MapKeys with the result from your ValueOf (see the answer https://stackoverflow.com/a/38186057/714501)
This may help:
b := []byte(`{"keyw":"value"}`)
var f interface{}
json.Unmarshal(b, &f)
myMap := f.(map[string]interface{})
fmt.Println(myMap)
Another way to convert an interface{} into a map with the package reflect is with MapRange.
I quote:
MapRange returns a range iterator for a map. It panics if v's Kind is
not Map.
Call Next to advance the iterator, and Key/Value to access each entry.
Next returns false when the iterator is exhausted. MapRange follows
the same iteration semantics as a range statement.
Example:
iter := reflect.ValueOf(m).MapRange()
for iter.Next() {
key := iter.Key().Interface()
value := iter.Value().Interface()
...
}

Iterate through a map of interface that contains different levels of maps

So lets say I have a map of interface like this:
c := map[string]interface{} {
"test": test,
"test2": test2,
}
Assuming that test is a map[string]map[string]map[string]string and test2 is map[string]string.
How would I create a for loop that would enumerate each index of the map and would enumerate through each index's map also?
So far I have gotten:
func sanitize_map(m map[string]interface{}) map[string]interface{} {
for k, v := range m {
//Here is where I want to enumerate through the map of k
}
return m
}
No need for reflection; use a type assertion and pass the value back to your sanitize function
func sanitizeMap(m map[string]interface{}) map[string]interface{} {
for k, v := range m {
_ = k
if v, ok := v.(map[string]interface{}); ok {
sanitizeMap(v)
}
}
return m
}
You can use reflect:
import "reflect"
func sanitize_map(m map[string]interface{}) map[string]interface{} {
for k, v := range m {
// Do something with the key k
kind := reflect.ValueOf(v).Kind()
if kind == reflect.Map {
// You have to be sure the value is of type map[string]interface{}
newValue := v.(map[string]interface{})
// recursively call sanitize
sanitize_map(newValue)
}
}
return m
}
The carveat is: every value in the map has to be either not a map (atom) or a map[string]interface{}. Note map[string]interface{} and map[string]map[string]interface{} are completely unrelated types, and you cannot use a type assertion of the second type on the first one.
However, you can put a map[string]map[string]string in a map[string]interface{}, like this:
innerMap1 := make(map[string]interface{})
// map to strings
innerMap1["a"] = "String 1"
innerMap2 := make(map[string]interface{})
// set mappings, maybe to other types
outerMap := make(map[string]interface{})
outerMap["ABC"] = innerMap1
outerMap["DEF"] = innerMap2
Now you can pass outerMap to the function, and reflect will automatically "strip" the layers of maps for you.

More easy way of using Interfaces to map YAML dynamically?

I am trying to parse a yaml file dynamically (Therefore no struct).
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"log"
)
func main() {
var out = `
a: First!
f: Second
b:
c:
f: Third
`
m := make(map[interface{}]interface{})
err := yaml.Unmarshal([]byte(out), &m)
if err != nil {
log.Fatal(err)
}
fmt.Println(m["b"].(map[interface{}]interface{})["c"].(map[interface{}]interface{})["f"])
}
Everytime I have to access a subkey, I am forced to convert map variable in question to (map[interface{}]interface{}). This is causing bit of a hassle for me as I have to iterate through the map.
Is there any easier method for parsing YAML file in Go?
Another approach is to flatten the yaml data structure into a key,value map in which keys and values are strings. Then if you need the actual type (5 being an int) you can do the conversion yourself. Example:
"a" = "First!"
"f" = "Second"
"b.c.f" = "Third"
"b.c.g.size" = "2"
"b.c.g.0 = "zero"
"b.c.g.1 = "one"
In Go:
func main() {
any := map[string]interface{}{}
err := yaml.Unmarshal([]byte(out), &any)
if err != nil {
log.Fatal(err)
}
flatmap := map[string]string{}
for k, v := range any {
flatten(k, v, flatmap)
}
for k, v := range flatmap {
fmt.Println(k, "=", v)
}
}
func flatten(prefix string, value interface{}, flatmap map[string]string) {
submap, ok := value.(map[interface{}]interface{})
if ok {
for k, v := range submap {
flatten(prefix+"."+k.(string), v, flatmap)
}
return
}
stringlist, ok := value.([]interface{})
if ok {
flatten(fmt.Sprintf("%s.size", prefix), len(stringlist), flatmap)
for i, v := range stringlist {
flatten(fmt.Sprintf("%s.%d", prefix, i), v, flatmap)
}
return
}
flatmap[prefix] = fmt.Sprintf("%v", value)
}

Resources