Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Sorting slice of structs by big.Int value

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

Playground link

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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)

    }
}

>Solution :

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 struct is also needless, you can sort a slice of *big.Int similarly.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading