feat(Go-Tool): ArrayList添加深度复制方法以及单测类、添加Rand随机获取参数方法、RandByWeight根据权重随机获取奖励方法
This commit is contained in:
@@ -21,3 +21,5 @@
|
|||||||
2020/5/7 : 创建timed包相关时间操作工具,实现时间戳、时间格式化操作。创建timed测试类
|
2020/5/7 : 创建timed包相关时间操作工具,实现时间戳、时间格式化操作。创建timed测试类
|
||||||
|
|
||||||
2020/6/15: 创建Set,实现相关方法
|
2020/6/15: 创建Set,实现相关方法
|
||||||
|
|
||||||
|
2020/6/30: ArrayList添加深度复制方法以及单测类、添加Rand随机获取参数方法、RandByWeight根据权重随机获取奖励方法
|
||||||
@@ -91,6 +91,11 @@ func TestJoin(t *testing.T) {
|
|||||||
union(mm, mm2)
|
union(mm, mm2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEqual(t *testing.T) {
|
||||||
|
DeepCopyIntSlice()
|
||||||
|
DeepCopyIntSlice2()
|
||||||
|
}
|
||||||
|
|
||||||
func intersection(mm, nn []interface{}) {
|
func intersection(mm, nn []interface{}) {
|
||||||
i1 := array.Intersection(mm, nn)
|
i1 := array.Intersection(mm, nn)
|
||||||
for _, row := range i1 {
|
for _, row := range i1 {
|
||||||
@@ -116,6 +121,18 @@ func union(mm, nn []interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeepCopyIntSlice() {
|
||||||
|
src := []int{1, 2, 3, 4, 5, 6}
|
||||||
|
src1 := array.DeepCopyIntSlice(src)
|
||||||
|
fmt.Println(&src == &src1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeepCopyIntSlice2() {
|
||||||
|
src := [][]int{{1, 2, 3}, {4, 5, 6}}
|
||||||
|
src1 := array.DeepCopyIntSlice2(src)
|
||||||
|
fmt.Println(&src == &src1)
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
mm = make([]interface{}, 0)
|
mm = make([]interface{}, 0)
|
||||||
mm1 = make([]interface{}, 0)
|
mm1 = make([]interface{}, 0)
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* @Author : huangzj
|
||||||
|
* @Time : 2020/6/29 17:16
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
|
||||||
|
package rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Go-Tool/util/rand"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRandByWeight(t *testing.T) {
|
||||||
|
fmt.Printf(strconv.Itoa(rand.GetRandValueByWeight([]int{10, 20, 30, 50})))
|
||||||
|
|
||||||
|
list, list1 := rand.GetAwardByWeight([][]int{{2, 2, 10}, {3, 3, 4}})
|
||||||
|
for _, r := range list {
|
||||||
|
fmt.Println(strconv.Itoa(r))
|
||||||
|
}
|
||||||
|
for _, r := range list1 {
|
||||||
|
fmt.Println(strconv.Itoa(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(rand.GetByWeight([]int{10, 11, 12, 13}, []int{20, 30, 40, 50}))
|
||||||
|
|
||||||
|
list2, list3 := rand.GetAwardByWeightWithLeftAward([][]int{{2, 3, 30}, {3, 3, 40}})
|
||||||
|
for _, r := range list2 {
|
||||||
|
fmt.Println(strconv.Itoa(r))
|
||||||
|
}
|
||||||
|
for _, r := range list3 {
|
||||||
|
for _, r1 := range r {
|
||||||
|
fmt.Println(strconv.Itoa(r1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list4 := rand.GetCountAwardsFromPool([][]int{{1, 2, 30}, {2, 2, 40}, {3, 2, 50}}, 2)
|
||||||
|
for _, r := range list4 {
|
||||||
|
for _, r1 := range r {
|
||||||
|
fmt.Println(strconv.Itoa(r1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list5 := rand.GetAwardByPercentage([][]int{{20, 3, 99}, {90, 3, 10}, {12, 3, 22}}, 100)
|
||||||
|
for _, r := range list5 {
|
||||||
|
fmt.Println(strconv.Itoa(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* @Author : huangzj
|
||||||
|
* @Time : 2020/6/29 17:15
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
|
||||||
|
package rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Go-Tool/util/rand"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRand(t *testing.T) {
|
||||||
|
fmt.Printf(strconv.Itoa(rand.GetRandInt(100, 2000)))
|
||||||
|
for _, r := range rand.GetRandIntNoRepeat(10, 100, 200) {
|
||||||
|
fmt.Printf(strconv.Itoa(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range rand.GetDiffNum([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 10) {
|
||||||
|
fmt.Printf(strconv.Itoa(r))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -104,3 +104,18 @@ func Union(aList, bList []interface{}) []interface{} {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeepCopyIntSlice(src []int) []int {
|
||||||
|
var clone = make([]int, len(src))
|
||||||
|
copy(clone, src)
|
||||||
|
return clone
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeepCopyIntSlice2(src [][]int) [][]int {
|
||||||
|
var clone = make([][]int, len(src))
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
clone[i] = DeepCopyIntSlice(src[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return clone
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* @Author : huangzj
|
||||||
|
* @Time : 2020/6/29 10:48
|
||||||
|
* @Description:这边的随机获取没有加锁,对于一些需要加锁的场景可以在外面再包装一层
|
||||||
|
*/
|
||||||
|
|
||||||
|
package rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
var R *rand.Rand
|
||||||
|
|
||||||
|
//获取min和max之间的一个随机数,返回值范围:[min,max]
|
||||||
|
func GetRandInt(min int, max int) int {
|
||||||
|
if min > max {
|
||||||
|
panic(fmt.Sprint("GetRandInt传入参数无效,min = ", min, ",max = ", max))
|
||||||
|
}
|
||||||
|
//Intn返回的结果是[0,n),所以这边会包含min和max
|
||||||
|
value := R.Intn(max-min+1) + min
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 随机算出count个数不重复
|
||||||
|
func GetRandIntNoRepeat(count, min, max int) []int {
|
||||||
|
if count > max-min+1 {
|
||||||
|
panic("数据错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
randAttr := make([]int, 0)
|
||||||
|
|
||||||
|
// 用于记录以及选中的数
|
||||||
|
selected := make(map[int]interface{}, 0)
|
||||||
|
|
||||||
|
for i := 1; i <= count; i++ {
|
||||||
|
randIndex := GetRandInt(min, max)
|
||||||
|
if _, ok := selected[randIndex]; ok {
|
||||||
|
i -= 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
selected[randIndex] = nil
|
||||||
|
randAttr = append(randAttr, randIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
return randAttr
|
||||||
|
}
|
||||||
|
|
||||||
|
//从一个数组中获取到X个不重复随机数
|
||||||
|
func GetDiffNum(data []int, count int) []int {
|
||||||
|
if count > len(data) {
|
||||||
|
panic("获取随机数数量有误")
|
||||||
|
}
|
||||||
|
diffList := make([]int, 0)
|
||||||
|
diffListIndex := GetRandIntNoRepeat(count, 0, len(data)-1)
|
||||||
|
for _, i := range diffListIndex {
|
||||||
|
diffList = append(diffList, data[i])
|
||||||
|
}
|
||||||
|
return diffList
|
||||||
|
}
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* @Author : huangzj
|
||||||
|
* @Time : 2020/6/29 10:23
|
||||||
|
* @Description:这边的随机获取没有加锁,对于一些需要加锁的场景可以在外面再包装一层
|
||||||
|
*/
|
||||||
|
|
||||||
|
package rand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"Go-Tool/util/array"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//传入一组包含权重的数组,计算权重,返回对应权重数组的下标(即对应权重获取的结果)
|
||||||
|
func GetRandValueByWeight(weightList []int) int {
|
||||||
|
//计算总的权重
|
||||||
|
totalWeight := 0
|
||||||
|
for _, value := range weightList {
|
||||||
|
totalWeight += value
|
||||||
|
}
|
||||||
|
nowRand := R.Intn(totalWeight)
|
||||||
|
rate := 0
|
||||||
|
for i := 0; i < len(weightList); i++ {
|
||||||
|
rate += weightList[i]
|
||||||
|
if nowRand < rate {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//通过权重获取奖励结果,这边的awardList的结构应该是 [[道具Id,道具数量,权重],....]
|
||||||
|
//返回结果的第一个元素是不包含权重的数组,第二个元素是包含权重的数组
|
||||||
|
func GetAwardByWeight(awardList [][]int) ([]int, []int) {
|
||||||
|
//这边应该加一个数组的检查.
|
||||||
|
weightListCheck(awardList)
|
||||||
|
|
||||||
|
//最后一位一定是权重.
|
||||||
|
weight := 0
|
||||||
|
for _, v := range awardList {
|
||||||
|
weight += v[len(v)-1]
|
||||||
|
}
|
||||||
|
randNum := GetRandInt(1, weight)
|
||||||
|
sum := 0
|
||||||
|
for _, v := range awardList {
|
||||||
|
sum += v[len(v)-1]
|
||||||
|
if sum >= randNum {
|
||||||
|
result := make([]int, 0)
|
||||||
|
weightResult := make([]int, 0)
|
||||||
|
return append(result, v[:len(v)-1]...), append(weightResult, v[:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据权重从列表获取元素
|
||||||
|
//入参分别是抽取的数字列表、权重列表
|
||||||
|
func GetByWeight(targetList []int, weightList []int) int {
|
||||||
|
//一开始就检查权重和对应的元素,长度是否一致
|
||||||
|
if len(targetList) != len(weightList) {
|
||||||
|
panic("权重和目标列表元素数量不匹配")
|
||||||
|
}
|
||||||
|
weight := 0
|
||||||
|
for _, v := range weightList {
|
||||||
|
weight += v
|
||||||
|
}
|
||||||
|
randNum := GetRandInt(1, weight)
|
||||||
|
sum := 0
|
||||||
|
for index, v := range weightList {
|
||||||
|
sum += v
|
||||||
|
if sum >= randNum {
|
||||||
|
return targetList[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据权重不放回的抽取,出参是:抽到的道具、剩余没有抽的道具
|
||||||
|
func GetAwardByWeightWithLeftAward(srcAwardList [][]int) ([]int, [][]int) {
|
||||||
|
//这边应该加一个数组的检查.
|
||||||
|
weightListCheck(srcAwardList)
|
||||||
|
|
||||||
|
awardList := array.DeepCopyIntSlice2(srcAwardList)
|
||||||
|
|
||||||
|
weight := 0
|
||||||
|
award := make([]int, 0)
|
||||||
|
leftAwards := make([][]int, 0)
|
||||||
|
for _, v := range awardList {
|
||||||
|
weight += v[len(v)-1]
|
||||||
|
}
|
||||||
|
randNum := GetRandInt(1, weight)
|
||||||
|
sum := 0
|
||||||
|
for index, v := range awardList {
|
||||||
|
sum += v[len(v)-1]
|
||||||
|
if sum >= randNum {
|
||||||
|
//如果获取到奖励则将当前获取的奖励扣除
|
||||||
|
leftAwards = append(awardList[0:index], awardList[index+1:]...)
|
||||||
|
award = v[:len(v)-1]
|
||||||
|
return award, leftAwards
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return award, leftAwards
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据权重不放回的抽取X个元素,直接返回这些元素
|
||||||
|
// 入参:奖池、抽取数量,出参:获得的所有道具
|
||||||
|
func GetCountAwardsFromPool(srcAwardPool [][]int, count int) [][]int {
|
||||||
|
awardPool := array.DeepCopyIntSlice2(srcAwardPool)
|
||||||
|
|
||||||
|
if count > len(awardPool) {
|
||||||
|
panic("抽取数量不对")
|
||||||
|
}
|
||||||
|
var finalAwardList [][]int
|
||||||
|
var award []int
|
||||||
|
var leftAward = make([][]int, len(awardPool))
|
||||||
|
copy(leftAward, awardPool)
|
||||||
|
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
award, leftAward = GetAwardByWeightWithLeftAward(leftAward)
|
||||||
|
finalAwardList = append(finalAwardList, award)
|
||||||
|
}
|
||||||
|
return finalAwardList
|
||||||
|
}
|
||||||
|
|
||||||
|
//通过百分比的方式来获取对应的数组,也就是说权重的总值可能超过传入的百分比数,此时取的只是0-百分比数的范围内
|
||||||
|
//所以这个方法可以按照概率取一个范围内的元素
|
||||||
|
func GetAwardByPercentage(srcAwardList [][]int, fullPercent int) []int {
|
||||||
|
weightListCheck(srcAwardList)
|
||||||
|
if fullPercent <= 0 {
|
||||||
|
panic("抽取概率不能小于等于0")
|
||||||
|
}
|
||||||
|
|
||||||
|
awardList := array.DeepCopyIntSlice2(srcAwardList)
|
||||||
|
|
||||||
|
randNum := GetRandInt(1, fullPercent)
|
||||||
|
sum := 0
|
||||||
|
for _, v := range awardList {
|
||||||
|
sum += v[len(v)-1]
|
||||||
|
if sum >= randNum {
|
||||||
|
result := make([]int, 0)
|
||||||
|
return append(result, v[:len(v)-1]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return []int{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func weightListCheck(awardList [][]int) {
|
||||||
|
for _, r := range awardList {
|
||||||
|
if len(r) == 0 {
|
||||||
|
panic("一维数组长度不能为0,必须存在权重")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitRand() {
|
||||||
|
R = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
InitRand()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user