按big.Int值对结构体切片进行排序

huangapple go评论78阅读模式
英文:

Sorting slice of structs by big.Int value

问题

我有一个结构体列表,应该按照结构体的fee值进行排序。我无法使用big.Intbig.Float,因为sort.Slice无法处理这些类型。因此,我创建了compareAmount变量,它是fee的转换为浮点数版本,并将其用于排序。问题是发生了整数溢出(我猜测),因此我得到了错误的结果。附上的代码产生以下输出:

-2530185498501831 -2.530185498501831e+18
-1018378616691543 -1.018378616691543e+18
-867409028382366 -8.67409028382366e+17
-288718783870437 -2.88718783870437e+17
-190626693543325 -1.90626693543325e+17
-15553651457149158 2.8930926165603937e+18

对象应该按从高到低的顺序列出,所以我认为正确的结果应该是-190626693543325是第一个元素,然后是-288718783870437作为第二个元素,因为它们最接近0。但是当我转换数字时发生了一些问题,列表没有按照我想要的方式排序。所以我的问题是,如何根据big.Int的值对结构体切片进行排序,并产生这个输出:

-190626693543325 -1.90626693543325e+17
-288718783870437 -2.88718783870437e+17
-867409028382366 -8.67409028382366e+17
-1018378616691543 -1.018378616691543e+18
-2530185498501831 -2.530185498501831e+18
-15553651457149158 2.8930926165603937e+18
英文:

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

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)

	}
}

答案1

得分: 3

big.Int有一个Int.Cmp()方法,所以你可以比较它们,这样你就可以直接对big.Int值进行排序,而无需进行任何转换。为了按降序排序并获得你想要的输出:

sort.Slice(feeList, func(i, j int) bool {
    return feeList[i].fee.Cmp(feeList[j].fee) > 0
})

Go Playground上尝试一下。

另外,如果你只想对数字进行排序,那么不需要使用包装结构体的切片,你可以类似地对*big.Int的切片进行排序。

英文:

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.

答案2

得分: 1

你可以避免使用float64字段,直接对数字进行排序:

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)
}
英文:

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

huangapple
  • 本文由 发表于 2022年8月13日 22:01:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/73344905.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定