英文:
Golang sort.SliceStable retrun different result after sort
问题
我使用sort.SliceStable对从txt文件中读取的map[string]int进行排序,但排序后的结果不同。我尝试将map转换为结构体或切片,但都没有成功,这种结果正常吗?
代码:
func TestStableUseSlice() {
counts := make(map[string]int)
f, err := os.Open("/Users/boroughfan/GitDocuments/GoLangPractise/ch01/dup/text_feel_the_light_lyrics.txt")
if err != nil {
fmt.Fprintf(os.Stderr, "dup:%v\n", err)
}
input := bufio.NewScanner(f)
for input.Scan() {
counts[input.Text()]++
}
f.Close()
///////////////////////////////////////////////////////////
linesSlice := make([]string, 0, len(counts))
for line := range counts {
linesSlice = append(linesSlice, line)
}
sort.SliceStable(linesSlice, func(i, j int) bool {
return counts[linesSlice[i]] < counts[linesSlice[j]]
})
for _, line := range linesSlice {
fmt.Printf("%d\t%s\n", counts[line], line)
}
}
func TestStableUsePair() {
counts := make(map[string]int)
f, err := os.Open("/Users/boroughfan/GitDocuments/GoLangPractise/ch01/dup/text_feel_the_light_lyrics.txt")
if err != nil {
fmt.Fprintf(os.Stderr, "dup:%v\n", err)
}
input := bufio.NewScanner(f)
for input.Scan() {
counts[input.Text()]++
}
f.Close()
///////////////////////////////////////////////////////////
pairList := make([]Pair, 0, len(counts))
for line := range counts {
pairList = append(pairList, Pair{line, counts[line]})
}
sort.SliceStable(pairList, func(i, j int) bool { return pairList[i].Value < pairList[j].Value })
for _, pairs := range pairList {
fmt.Printf("%d\t%s\n", pairs.Value, pairs.Key)
}
}
这是txt文件的内容:
// this is the dup test file, contents are from the feel the light lyrics
"Feel The Light"
(from "Home" soundtrack)
Hmm, hmm
Hmm
Here I go, here I go
Feel better now, feel better now
Here I go, here I go
It's better now,
<details>
<summary>英文:</summary>
I use sort.SliceStable for a map[string]int which read form a txt file, but after sort the results are different. I have tried translate the map to struct or slices but ethier wored, is it normally for the results?
code:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
func TestStableUseSlice() {
counts := make(map[string]int)
f, err := os.Open("/Users/boroughfan/GitDocuments/GoLangPractise/ch01/dup/text_feel_the_light_lyrics.txt")
if err != nil {
fmt.Fprintf(os.Stderr, "dup:%v\n", err)
}
input := bufio.NewScanner(f)
for input.Scan() {
counts[input.Text()]++
}
f.Close()
///////////////////////////////////////////////////////////
linesSlice := make([]string, 0, len(counts))
for line := range counts {
linesSlice = append(linesSlice, line)
}
sort.SliceStable(linesSlice, func(i, j int) bool {
return counts[linesSlice[i]] < counts[linesSlice[j]]
})
for _, line := range linesSlice {
fmt.Printf("%d\t%s\n", counts, line)
}
}
func TestStableUsePair() {
counts := make(map[string]int)
f, err := os.Open("/Users/boroughfan/GitDocuments/GoLangPractise/ch01/dup/text_feel_the_light_lyrics.txt")
if err != nil {
fmt.Fprintf(os.Stderr, "dup:%v\n", err)
}
input := bufio.NewScanner(f)
for input.Scan() {
counts[input.Text()]++
}
f.Close()
///////////////////////////////////////////////////////////
pairList := make([]Pair, 0, len(counts))
for line := range counts {
pairList = append(pairList, Pair{line, counts})
}
sort.SliceStable(pairList, func(i, j int) bool { return pairList[i].Value < pairList[j].Value })
for _, pairs := range pairList {
fmt.Printf("%d\t%s\n", pairs.Value, pairs.Key)
}
}
<!-- end snippet -->
here is the txt file:
```txt
// this is the dup test file, contents are from the feel the light lyrics
"Feel The Light"
(from "Home" soundtrack)
Hmm, hmm
Hmm
Here I go, here I go
Feel better now, feel better now
Here I go, here I go
It's better now, feel better now
Do you remember when we fell under
Did you expect me to reason with thunder
I still remember when time was frozen
What seemed forever was just a moment
Hurry up, hurry up
There's no more waiting
We're still worth saving
Feel the light
Shining in the dark of night
Remember what we forgot
I know it's a long shot
But we're bringing it all back
We're bringing it all back
Feel the light
Shining like the stars tonight
Remember what we forgot
I know it's a long shot
But we're bringing it all back
We're bringing it all back
Here I go, here I go
Feel better now, feel better now
Here I go, here I go
It's better now, feel better now
I still remember when things were broken
But put together the cracks we'll close in
Hurry up, hurry up
There's no more waiting
We're still worth saving
Feel the light
Shining in the dark of night
Remember what we forgot
I know it's a long shot
But we're bringing it all back
We're bringing it all back
Feel the light
Shining like the stars tonight
Remember what we forgot
I know it's a long shot
But we're bringing it all back
We're bringing it all back
You and I can have it all tonight
So let's bring it back to life
Now we have another chance to fly
Another chance to make it right
Feel the light
Shining in the dark of night
Remember what we forgot
I know it's a long shot
Feel the light
Shining like the stars tonight
Remember what we forgot
I know it's a long shot
But we're bringing it all back
We're bringing it all back
Here we go, here we go
Feel better now, feel better now
Here we go, here we go
It's better now, feel better now
答案1
得分: -1
对于 counts 中的每一行:
...
将按照映射给出的随机顺序枚举存储在 counts
映射中的行。
sort.SliceStable()
的 "stable" 部分不会使具有相同出现次数的两行变得无序,相反,它将保留这些行的初始顺序。
例如:
"Here we go, here we go"
和 "We're still worth saving"
都有出现次数为 2,所以:
如果 "Here we go, here we go"
在初始切片中出现在 "We're still worth saving"
之前(或之后),在调用 sort.SliceStable()
后,它仍然会在结果切片中保持在之前(或之后)。
如果你想要一个一致的顺序,可以选择一种完全排序行之间的方式:
sort.SliceStable(linesSlice, func(i, j int) bool {
if counts[linesSlice[i]] != counts[linesSlice[j]] {
return counts[linesSlice[i]] < counts[linesSlice[j]]
}
// 在这个例子中:如果行具有相同的计数,按字母顺序排序它们:
return linesSlice[i] < linesSlice[j]
})
(注意,如果元素之间的顺序是完全的,就不再需要 Stable
了)
英文:
for line := range counts {
...
will enumerate the lines stored in the counts
map following the randomized order given by the map.
The "stable" part of sort.SliceStable()
will not un-randomize two lines which have the same occurrence count in your text -- quite the contrary: it will preserve the initial order of such lines.
For example :
"Here we go, here we go"
and "We're still worth saving"
both have count 2, so :
if "Here we go, here we go"
appears before (resp. after) "We're still worth saving"
in your initial slice, it will remain before (resp. after) in the resulting slice after calling sort.SliceStable()
.
If you want a consistent order, choose a way to completely order the lines between them :
sort.SliceStable(linesSlice, func(i, j int) bool {
if counts[linesSlice[i]] != counts[linesSlice[j]] {
return counts[linesSlice[i]] < counts[linesSlice[j]]
}
// in this example: if lines have same count, order them alphabetically:
return linesSlice[i] < linesSlice[j]
})
(note that if the order between elements is complete, you don't need the Stable
anymore)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论