dow46218 2018-06-06 09:10

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

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

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 将GPDO_0引|脚设首成PWM1的输出引脚 实验编程该怎么写
• ¥50 阿里云服务器 CentOS7.9 搭建 openvpn 服务
• ¥100 开源软件弱点处理规范
• ¥15 excel如何根据文件名自动搜索并批量导入文件？
• ¥15 VScode 用户代码片段图标
• ¥15 streamingtool
• ¥15 MATLAB图像问题
• ¥20 树莓派5做人脸情感识别与反馈系统
• ¥15 selenium 控制 chrome-for-testing 在 Linux 环境下报错 SessionNotCreatedException
• ¥15 使用pyodbc操作SQL数据库