I have a list of structs which should be sorted by the fee
value of the structs. I couldn't use big.Int
and big.Float
because sort.Slice
won't work with these types. Therefore I created the compareAmount
variable which is the converted float version of fee
and use that for the sorting. The problem is that an integer overflow happens (I assume), therefore I get wrong results. The below attached code produces the following output:
-2530185498501831 -2.530185498501831e 18
-1018378616691543 -1.018378616691543e 18
-867409028382366 -8.67409028382366e 17
-288718783870437 -2.88718783870437e 17
-190626693543325 -1.90626693543325e 17
-15553651457149158 2.8930926165603937e 18
The objects should be listed from high to low, so I believe the correct result would be if -190626693543325
would be the first element, than -288718783870437
the second as these are closest to 0
. But something happens when I convert the numbers and the list is not sorted as I wanted. So my question is that how could I sort my slice of structs based on the big.Int
values and produce this output:
-190626693543325 -1.90626693543325e 17
-288718783870437 -2.88718783870437e 17
-867409028382366 -8.67409028382366e 17
-1018378616691543 -1.018378616691543e 18
-2530185498501831 -2.530185498501831e 18
-15553651457149158 2.8930926165603937e 18
package main
import (
"fmt"
"math/big"
"sort"
)
func divBigInt(num *big.Int) *big.Int {
divider := big.NewInt(1000)
divided := big.NewInt(0).Mul(num, divider)
return divided
}
type compareStruct struct {
fee *big.Int
compareAmount float64
}
func main() {
fee1 := big.NewInt(-288718783870437)
fee2 := big.NewInt(-867409028382366)
fee3 := big.NewInt(-190626693543325)
fee4 := big.NewInt(-1018378616691543)
fee5 := big.NewInt(-15553651457149158)
fee6 := big.NewInt(-2530185498501831)
fees := make([]*big.Int, 0)
fees = append(fees, fee1)
fees = append(fees, fee2)
fees = append(fees, fee3)
fees = append(fees, fee4)
fees = append(fees, fee5)
fees = append(fees, fee6)
feeList := make([]compareStruct, 0)
for _, f := range fees {
i1 := compareStruct{fee: f, compareAmount: float64(divBigInt(f).Int64())}
feeList = append(feeList, i1)
}
sort.Slice(feeList, func(i, j int) bool {
return feeList[i].compareAmount < feeList[j].compareAmount
})
for _, x := range feeList {
fmt.Println(x.fee, x.compareAmount)
}
}
CodePudding user response:
big.Int
has an Int.Cmp()
method, so you can compare them, so you can directly sort big.Int
values without any conversion. To sort them descendant to get your desired output:
sort.Slice(feeList, func(i, j int) bool {
return feeList[i].fee.Cmp(feeList[j].fee) > 0
})
Try it on the Go Playground.
Also, if you just want to sort the numbers, the slice of wrapper structs is also needless, you can sort a slice of *big.Int
similarly.
CodePudding user response:
You can avoid the need for the float64
field and just sort the numbers directly:
package main
import (
"fmt"
"math/big"
"sort"
)
func main() {
fees := []*big.Int{
big.NewInt(-288718783870437),
big.NewInt(-867409028382366),
big.NewInt(-190626693543325),
big.NewInt(-1018378616691543),
big.NewInt(-15553651457149158),
big.NewInt(-2530185498501831),
}
sort.Slice(fees, func(a, b int) bool {
// sort direction high before low.
return fees[a].Cmp(fees[b]) > 0
})
fmt.Println("fees", fees)
}