请看下面我的地图
var romanNumeralDict map[int]string = map[int]string{
1000: "M",
900 : "CM",
500 : "D",
400 : "CD",
100 : "C",
90 : "XC",
50 : "L",
40 : "XL",
10 : "X",
9 : "IX",
5 : "V",
4 : "IV",
1 : "I",
}
Run Code Online (Sandbox Code Playgroud)
我希望按照键的大小顺序遍历此映射
for k, v := range romanNumeralDict {
fmt.Println("k:", k, "v:", v)
}
Run Code Online (Sandbox Code Playgroud)
然而,这打印出来
k: 1000 v: M
k: 40 v: XL
k: 5 v: V
k: 4 v: IV
k: 900 v: CM
k: …Run Code Online (Sandbox Code Playgroud) 在阅读了 Dave Cheney关于 Go 地图的博客文章后,我仍然有一些不清楚的地方。
域名注册地址:
在挖掘运行时包后,我发现底层地图结构如下:
// A header for a Go map.
type hmap struct {
// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
// Make sure this stays in sync with the compiler's definition.
count int // # live cells == size of map. Must be first (used by len() builtin)
flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * …Run Code Online (Sandbox Code Playgroud) 我可以依赖地图的随机迭代顺序来实现Web应用程序中客户端的随机"配对"吗?我试过环顾四周,但似乎无法找到这种随机性随机性的细分.
该算法看起来像:
var clients map[Client]struct{}
func PairClient(c Client) (Client, error) {
for m := range clients {
if m != c {
return m, nil
}
}
return nil, fmt.Errorf("lobby: insufficient number of clients")
}
Run Code Online (Sandbox Code Playgroud)
当有超过1000个连接的客户端时,这是否足够,或者我应该维护一个单独的客户端片并从中随机选择?
我使用了一个地图,它使用句子中的单词作为键,整数作为值.
func WordCount(s string) map[string]int {
var m map[string]int
m = make(map[string]int)
var substrings[]string
count := 0
substrings = strings.Split(s, " ")
for i := range substrings {
count = count + 1
m[substrings[i]] = count
}
return m
}
func main() {
fmt.Println(WordCount("I am learning GO since some days"))
}
Run Code Online (Sandbox Code Playgroud)
以上代码始终以正确的顺序显示地图,即
map[I:1 am:2 learning:3 GO:4 since:5 some:6 days:7]
Run Code Online (Sandbox Code Playgroud)
但如果我改变
count = count + 1
Run Code Online (Sandbox Code Playgroud)
至
count++
Run Code Online (Sandbox Code Playgroud)
输出更改为:
map[learning:3 GO:4 since:5 some:6 days:7 I:1 am:2]
Run Code Online (Sandbox Code Playgroud)
我知道地图迭代在Golang中是随机的,但为什么count = …
我正在寻找一种确定Go map的有序范围.
Golang规范说明如下:
未指定地图上的迭代顺序,并且不保证从一次迭代到下一次迭代是相同的.如果在迭代期间删除了尚未到达的映射条目,则不会生成相应的迭代值.如果在迭代期间创建了映射条目,则可以在迭代期间生成该条目,或者可以跳过该条目.对于创建的每个条目以及从一次迭代到下一次迭代,选择可能不同.如果映射为nil,则迭代次数为0.
我在StackOverflow和Google上找到的所有内容都是(imho)我不喜欢的解决方法.
有没有一种可靠的方法来迭代地图并按照它们插入的顺序检索项目?
我发现的解决方案是:
在两个单独的切片中跟踪键和值:听起来像"不要使用地图",失去了使用地图的所有优点.
使用映射但跟踪不同切片中的密钥:这意味着数据重复可能导致数据不对齐,并最终可能带来大量错误和痛苦的调试.
你有什么建议?
编辑以响应可能的重复标记.
我的问题和提供的问题(这个问题,但也是这个问题)之间存在细微的差别,这两个问题都要求在按键字典顺序之后循环遍历地图; 相反,我特别问过:
有没有一种可靠的方法来迭代地图并按照它们插入的顺序检索项目?
这不是词典,因此不同于@gramme.ninja问题:
如何让键按顺序/排序地图,以便键按顺序排列并且值对应?
从Golang 源代码看,它们似乎遵循哈希表(即存储桶数组)的相当标准的实现。基于此,对于不变的映射,迭代应该是确定性的(即按顺序迭代数组,然后按顺序在存储桶中迭代)。他们为什么要使迭代是随机的?
在第一种情况下,我按值传递一个映射: package main
import (
"fmt"
"time"
)
func timeMap(z map[string]interface{}) {
z["updated_at"] = time.Now()
}
func main() {
foo := map[string]interface{}{
"Matt": 42,
}
timeMap(foo)
fmt.Println(foo)
}
Run Code Online (Sandbox Code Playgroud)
输出是一个静音地图:
map[updated_at:2009-11-10 23:00:00 +0000 UTC Matt:42]
Run Code Online (Sandbox Code Playgroud)
在第二种情况下,代码几乎相同,但通过引用传递:
package main
import (
"fmt"
"time"
)
func timeMap(z *map[string]interface{}) {
(*z)["updated_at"] = time.Now()
}
func main() {
foo := map[string]interface{}{
"Matt": 42,
}
timeMap(&foo)
fmt.Println(foo)
}
Run Code Online (Sandbox Code Playgroud)
显然,结果不同:
map[Matt:42 updated_at:2009-11-10 23:00:00 +0000 UTC]
Run Code Online (Sandbox Code Playgroud)
我的期望如下:
在我的应用程序中,我得到一些未指定的 json 字符串,并希望循环遍历 json 字符串的值。我使用函数 json.Unmarshal() 从 json 值获取对象列表。效果很好。但不幸的是,我得到了 json 值的随机列表,而不是它们的原始顺序。我使用这个示例代码:
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonstr := `{
"@odata.context": "http://services.odata.org/V4/TripPinService/$metadata#People/$entity",
"@odata.id": "http://services.odata.org/V4/TripPinService/People('russellwhyte')",
"@odata.etag": "W/\"08D956FAB7E22152\"",
"@odata.editLink": "http://services.odata.org/V4/TripPinService/People('russellwhyte')",
"UserName": "russellwhyte",
"FirstName": "Russell",
"LastName": "Whyte",
"Gender": "Male",
"Concurrency": 637636457076498770
}`
var result interface{}
if err := json.Unmarshal([]byte(jsonstr), &result); err != nil {
fmt.Println("Can't convert json to object.")
fmt.Println(err.Error())
}
odataobjs := result.(map[string]interface{})
for k, v := range odataobjs {
fmt.Print(fmt.Sprintln(k, v))
}
}
Run Code Online (Sandbox Code Playgroud)
请参阅go-playground。
这可能是一些结果列表: …
go ×9
dictionary ×5
hashmap ×4
for-range ×1
function ×1
json ×1
loops ×1
mutability ×1
pointers ×1
random ×1