Golang sort.SliceStable在排序后返回不同的结果

huangapple go评论74阅读模式
英文:

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:

&lt;!-- begin snippet: js hide: false console: true babel: false --&gt;

&lt;!-- language: lang-html --&gt;

    func TestStableUseSlice() {
    	counts := make(map[string]int)
    	f, err := os.Open(&quot;/Users/boroughfan/GitDocuments/GoLangPractise/ch01/dup/text_feel_the_light_lyrics.txt&quot;)
    	if err != nil {
    		fmt.Fprintf(os.Stderr, &quot;dup:%v\n&quot;, 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]] &lt; counts[linesSlice[j]]
    	})

    	for _, line := range linesSlice {
    		fmt.Printf(&quot;%d\t%s\n&quot;, counts
, line)
} } func TestStableUsePair() { counts := make(map[string]int) f, err := os.Open(&quot;/Users/boroughfan/GitDocuments/GoLangPractise/ch01/dup/text_feel_the_light_lyrics.txt&quot;) if err != nil { fmt.Fprintf(os.Stderr, &quot;dup:%v\n&quot;, 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 &lt; pairList[j].Value }) for _, pairs := range pairList { fmt.Printf(&quot;%d\t%s\n&quot;, pairs.Value, pairs.Key) } } &lt;!-- end snippet --&gt; here is the txt file: ```txt // this is the dup test file, contents are from the feel the light lyrics &quot;Feel The Light&quot; (from &quot;Home&quot; soundtrack) Hmm, hmm Hmm Here I go, here I go Feel better now, feel better now Here I go, here I go It&#39;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&#39;s no more waiting We&#39;re still worth saving Feel the light Shining in the dark of night Remember what we forgot I know it&#39;s a long shot But we&#39;re bringing it all back We&#39;re bringing it all back Feel the light Shining like the stars tonight Remember what we forgot I know it&#39;s a long shot But we&#39;re bringing it all back We&#39;re bringing it all back Here I go, here I go Feel better now, feel better now Here I go, here I go It&#39;s better now, feel better now I still remember when things were broken But put together the cracks we&#39;ll close in Hurry up, hurry up There&#39;s no more waiting We&#39;re still worth saving Feel the light Shining in the dark of night Remember what we forgot I know it&#39;s a long shot But we&#39;re bringing it all back We&#39;re bringing it all back Feel the light Shining like the stars tonight Remember what we forgot I know it&#39;s a long shot But we&#39;re bringing it all back We&#39;re bringing it all back You and I can have it all tonight So let&#39;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&#39;s a long shot Feel the light Shining like the stars tonight Remember what we forgot I know it&#39;s a long shot But we&#39;re bringing it all back We&#39;re bringing it all back Here we go, here we go Feel better now, feel better now Here we go, here we go It&#39;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 :

&quot;Here we go, here we go&quot; and &quot;We&#39;re still worth saving&quot; both have count 2, so :

if &quot;Here we go, here we go&quot; appears before (resp. after) &quot;We&#39;re still worth saving&quot; 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]] &lt; counts[linesSlice[j]]
}
// in this example: if lines have same count, order them alphabetically:
return linesSlice[i] &lt; linesSlice[j]
})

(note that if the order between elements is complete, you don't need the Stable anymore)

huangapple
  • 本文由 发表于 2022年8月1日 22:29:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/73195260.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定