Home > Software engineering >  Golang sort.SliceStable retrun different result after sort
Golang sort.SliceStable retrun different result after sort

Time:08-03

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:

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

here is the txt file:

// 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

CodePudding user response:

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)

  •  Tags:  
  • go
  • Related