Matías Salen
Matías Salen

Reputation: 43

Sort struct by order of string with same values

I'm trying to sort a collection of structs by the order of another strings characters with the same values.

Here's an example:

package main

import (
    "fmt"
    "sort"
    "strings"
)

type Container struct {
    Initial  string
}

func main() {
    s := "dfah"
    c := []Container{}

    for _, r := range "fadh" {
        c = append(c, Container{Initial: string(r)})
    }

    sort.Slice(c, func(i, j int) bool {
        str := strings.Compare(c[i].Initial, s)

        if str == -1 {
            return true
        } else {
            return false
        }
    })

    fmt.Printf("Result: %s\n", c) // returns 'dafh'
    fmt.Printf("Desired result: %s\n", s) // returns 'dfah'
}

The desired result would be the sorted collection of Container structs, with the same order of the 'dfah' string.

https://play.golang.org/p/eDW5-xpCzv

They will always have the same characters/number of characters, just unsorted. I'm not sure what the correct way to accomplish this is. Any ideas? Thanks!

Upvotes: 0

Views: 394

Answers (1)

Paul Hankin
Paul Hankin

Reputation: 58369

In your slice-sorting function, you're comparing c[i].Initial to s. That's simply wrong. Instead, you want to find whether c[i].Initial appears in s before or after c[j].Initial.

Here's some example code, or see it running on the playground:

package main

import (
    "fmt"
    "sort"
    "strings"
)

type Container struct {
    Initial string
}

func main() {
    s := "dfah"
    c := []Container{}

    for _, r := range "fadh" {
        c = append(c, Container{Initial: string(r)})
    }

    sort.Slice(c, func(i, j int) bool {
        return strings.Index(s, c[i].Initial) <= strings.Index(s, c[j].Initial)
    })

    fmt.Printf("Result: %s\n", c)         // returns [{d} {f} {a} {h}]
    fmt.Printf("Desired result: %s\n", s) // returns 'dfah'
}

Note in practice, this is inefficient, since it involves scanning s lots of times. If this were real code, I'd be building a map from characters of s to their index so that the strings.Index calls could be replaced by map lookups.

Upvotes: 1

Related Questions