dow46218 2018-06-06 09:10
浏览 23
已采纳

用于遍历地图的Golang不会返回不一致的值[重复]

This question already has an answer here:

I am writing a probability model that will take any number of "Outcome"s, then when a number is rolled and passed into the model the correct "Outcome" will be returned;

Essentially the logic is a map of outcomes with indexes representing that outcomes particular weight.

Outcome One 25% Outcome Two 25% Outcome Three 50%

these values will translate to;

outcomes := make(map[int]Outcome)
outcomes[25] = Outcome{"Outcome One", 25}
outcomes[50] = Outcome{"Outcome One", 25}
outcomes[100] = Outcome{"Outcome One", 50}

I have a function that then takes an input lets say 10, and loops around outcomes until the index is larger than the input;

Expected

input: 10, output: Outcome{"Outcome One", 25}
input: 30, output: Outcome{"Outcome Two", 25}
input: 60, output: Outcome{"Outcome Two", 50}

However in my unit tests for an input of 10, I get a combination of "Outcome One" and "Outcome Two", I think the problem lies within my for loop.

ProbabilityMatrix_test.go

var outcome1 = Outcome{"Outcome One", 25}
var outcome2 = Outcome{"Outcome Two", 25}
var outcome3 = Outcome{"Outcome Three", 50}

probabilityMatrix := ProbabilityMatrix{}
probabilityMatrix.SetUp()

probabilityMatrix.AddOutcome(outcome1)
probabilityMatrix.AddOutcome(outcome2)
probabilityMatrix.AddOutcome(outcome3)

outcome := probabilityMatrix.RollA(10)

if outcome != outcome1 {
    t.Errorf("%s", probabilityMatrix.Delimiters)
    t.Errorf("incorrect outcome, got %s, expected %s", outcome.Name, outcome1.Name)
}

The below code returns Outcome One, around 75% of the time (correct), and Outcome Two 25%

package RealisticTemperatureGenerator

type Outcome struct {
    Name        string
    Probability int
}

type ProbabilityMatrix struct {
    Delimiters     map[int]Outcome
    DefaultOutcome Outcome
    Total          int
}

func (pm *ProbabilityMatrix) SetUp() {
    pm.Delimiters = make(map[int]Outcome)
    pm.Total = 0
}

func (pm *ProbabilityMatrix) AddOutcome(outcome Outcome) {

    pm.DefaultOutcome = outcome
    currentIndex := outcome.Probability + pm.Total
    pm.Delimiters[currentIndex] = outcome
    pm.Total = currentIndex
}

func (pm *ProbabilityMatrix) RollA(input int) Outcome {
  return pm.WalkDelimiters(input)
}

// Problem Possibly here
func (pm ProbabilityMatrix) WalkDelimiters(input int) Outcome {

  for key, _ := range pm.Delimiters {
      if pm.Delimiters[key].Probability >= input {
        return pm.Delimiters[key]
      }
  }
  return pm.DefaultOutcome
}
</div>
  • 写回答

1条回答 默认 最新

  • douzhaolu4780 2018-06-06 09:12
    关注

    When looping over maps in golang the order of the returned elements is random. This is the reason for the inconsistent behavior. See "Iteration order" in the official blog: https://blog.golang.org/go-maps-in-action

    If you want a stable order, you have to maintain the keys in another structure:

    keys := []int{25, 50, 100}
    
    for _, key := range keys {
        if pm.Delimiters[key].Probability >= input {
            return pm.Delimiters[key]
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值