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:
langMap := make(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.