根据另一个切片中元素的顺序对切片进行排序

I am attempting to order a slice based on the order of the elements within another slice. My sort function works when I only have one of each type within my slice I want to order however when I start adding more elements the ordering breaks.

I have created an example within the Golang playground.

https://play.golang.org/p/e9sHIeV2qSf

I want to order my Variant slice by the Code field and have it the same as order as the codes appear in the Language struct.

Below is the sort function I am using:

sort.Slice(variants, func(i, j int) bool {
    for k, language := range languages {
        if language.Code == variants[i].Code {
            return i >= k
        }
    }

    return false
})

The current order it's returning is:

Sorted slice: [{Code:en-GB} {Code:en-US} {Code:en-GB} {Code:es-ES} {Code:en-GB} {Code:en-GB} {Code:en-GB} {Code:en-GB} {Code:es-ES}]

When the order within my Language struct is:

"en-GB", "en-US", "fr-FR", "es-ES"

I think to do this, you need to build a ranking of your languages:

var langMap map[string]int
for i, lang := range languages {
    langMap[lang.Code] = i
}

With this, it becomes trivial to just look up the ranking of each item in variants, and return the appropriate value:

sort.Slice(variants, func(i, j int) bool {
    iRank, jRank := langMap[variants[i].Code], langMap[variants[j].Code]
    return iRank < jRank
})

If there's a chance you may have inputs that are not in the pre-sorted list, you can sort them last:

sort.Slice(variants, func(i, j int) bool {
    iRank, iExists := langMap[variants[i].Code]
    jRank, jExists := langMap[variants[j].Code]
    switch (
    case iExists && jExists:
        // Both exist in the pre-ordered list, so sort by rank
        return iRank < jRank
    case !iExists && !jExists:
        // Neither exists in the pre-ordered list, sort alphabetically
        return variants[i].Code < variants[j].Code
    case iExists:
        // Only i exists, so sort it before j
        return true
    default: // jExists
        // Only j exists, so sort it after i
        return false
    )

})

It is logically possible to do the same by looping through your reference list each time, as you're attempting, but it's much harder to reason about, and far less efficient.