In Golang, how can I sort a list of strings alphabetically without completely ignoring case?

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

In Golang, how can I sort a list of strings alphabetically without completely ignoring case?

问题

我希望字符串按字母顺序排序,并且可以控制是否将"A"排在"a"之前。

在Less()函数中使用strings.ToLower()无法实现这一点。有时候"A"会排在"a"之前,有时候会排在之后。

英文:

I want the strings to be sorted alphabetically with control over whether "A" comes before "a".

In the Less() function using strings.ToLower() doesn't achieve this. Sometimes "A" comes before "a", and sometimes after.

答案1

得分: 6

而不是使用strings.ToLower比较整个字符串,可以比较单个符文。

type ByCase []string

func (s ByCase) Len() int      { return len(s) }
func (s ByCase) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s ByCase) Less(i, j int) bool {
    iRunes := []rune(s[i])
    jRunes := []rune(s[j])

    max := len(iRunes)
    if max > len(jRunes) {
        max = len(jRunes)
    }

    for idx := 0; idx < max; idx++ {
        ir := iRunes[idx]
        jr := jRunes[idx]

        lir := unicode.ToLower(ir)
        ljr := unicode.ToLower(jr)

        if lir != ljr {
            return lir < ljr
        }

        // the lowercase runes are the same, so compare the original
        if ir != jr {
            return ir < jr
        }
    }

    // 如果字符串在最短字符串的长度范围内相同,则较短的字符串排在前面
    return len(iRunes) < len(jRunes)
}

你需要翻译的内容已经翻译完毕,请确认是否满意。

英文:

instead of comparing the entire string using strings.ToLower, compare the individual runes.

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

type ByCase []string

func (s ByCase) Len() int      { return len(s) }
func (s ByCase) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s ByCase) Less(i, j int) bool {
	iRunes := []rune(s[i])
	jRunes := []rune(s[j])

	max := len(iRunes)
	if max &gt; len(jRunes) {
		max = len(jRunes)
	}

	for idx := 0; idx &lt; max; idx++ {
		ir := iRunes[idx]
		jr := jRunes[idx]

		lir := unicode.ToLower(ir)
		ljr := unicode.ToLower(jr)

		if lir != ljr {
			return lir &lt; ljr
		}

		// the lowercase runes are the same, so compare the original
		if ir != jr {
			return ir &lt; jr
		}
	}

    // If the strings are the same up to the length of the shortest string, 
    // the shorter string comes first
	return len(iRunes) &lt; len(jRunes)
}

答案2

得分: 5

这可能是一个解决方案:

package main

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

var listOfStrings []string = []string{
    "mars bar",
    "milk-duds",
    "Mars bar",
    "milk",
    "milky-way",
    "Milk",
    "Milky-way",
    "mars",
}

type Alphabetic []string

func (list Alphabetic) Len() int { return len(list) }

func (list Alphabetic) Swap(i, j int) { list[i], list[j] = list[j], list[i] }

func (list Alphabetic) Less(i, j int) bool {
    var si string = list[i]
    var sj string = list[j]
    var si_lower = strings.ToLower(si)
    var sj_lower = strings.ToLower(sj)
    if si_lower == sj_lower {
        return si < sj
    }
    return si_lower < sj_lower
}

func main() {
    fmt.Println("UNSORTED")
    printStrings(listOfStrings)
    sort.Sort(Alphabetic(listOfStrings))
    fmt.Println()
    fmt.Println("SORTED ALPHABETICALLY")
    printStrings(listOfStrings)
}

func printStrings(slice []string) {
    for i := 0; i < len(slice); i++ {
        fmt.Println(slice[i])
    }
}

以下是输出结果:

UNSORTED
mars bar
milk-duds
Mars bar
milk
milky-way
Milk
Milky-way
mars

SORTED ALPHABETICALLY
mars
Mars bar
mars bar
Milk
milk
milk-duds
Milky-way
milky-way
英文:

This may be a solution:

package main

import (
    &quot;strings&quot;
    &quot;sort&quot;
    &quot;fmt&quot;
)

var listOfStrings []string = []string{
    &quot;mars bar&quot;,
    &quot;milk-duds&quot;,
    &quot;Mars bar&quot;,
    &quot;milk&quot;,
    &quot;milky-way&quot;,
    &quot;Milk&quot;,
    &quot;Milky-way&quot;,
    &quot;mars&quot;,
}

type Alphabetic []string

func (list Alphabetic) Len() int { return len(list) }

func (list Alphabetic) Swap(i, j int) { list[i], list[j] = list[j], list[i] }

func (list Alphabetic) Less(i, j int) bool {
    var si string = list[i]
    var sj string = list[j]
    var si_lower = strings.ToLower(si)
    var sj_lower = strings.ToLower(sj)
    if si_lower == sj_lower {
        return si &lt; sj
    }
    return si_lower &lt; sj_lower
}

func main() {
    fmt.Println(&quot;UNSORTED&quot;)
    printStrings(listOfStrings)
    sort.Sort(Alphabetic(listOfStrings))
    fmt.Println()
    fmt.Println(&quot;SORTED ALPHABETICALLY&quot;)
    printStrings(listOfStrings)
}

func printStrings(slice []string) {
    for i := 0; i &lt; len(slice); i++ {
        fmt.Println(slice[i])
    }
}

Here's the output:

UNSORTED
mars bar
milk-duds
Mars bar
milk
milky-way
Milk
Milky-way
mars

SORTED ALPHABETICALLY
mars
Mars bar
mars bar
Milk
milk
milk-duds
Milky-way
milky-way

答案3

得分: 1

这是一个使用strings.Map的Unicode友好方法:

package main

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

type slice struct { sort.StringSlice }

func (s slice) Less(d, e int) bool {
   t := strings.Map(unicode.ToUpper, s.StringSlice[d])
   u := strings.Map(unicode.ToUpper, s.StringSlice[e])
   return t < u
}

func main() {
   a := slice{
      sort.StringSlice{"a", "b", "A", "B"},
   }
   sort.Sort(a)
   fmt.Println(a.StringSlice) // [a A b B]
}

https://golang.org/pkg/strings#Map

英文:

Heres a Unicode friendly method that utilizes strings.Map:

package main

import (
   &quot;fmt&quot;
   &quot;sort&quot;
   &quot;strings&quot;
   &quot;unicode&quot;
)

type slice struct { sort.StringSlice }

func (s slice) Less(d, e int) bool {
   t := strings.Map(unicode.ToUpper, s.StringSlice[d])
   u := strings.Map(unicode.ToUpper, s.StringSlice[e])
   return t &lt; u
}

func main() {
   a := slice{
      sort.StringSlice{&quot;a&quot;, &quot;b&quot;, &quot;A&quot;, &quot;B&quot;},
   }
   sort.Sort(a)
   fmt.Println(a.StringSlice) // [a A b B]
}

https://golang.org/pkg/strings#Map

huangapple
  • 本文由 发表于 2016年1月29日 10:57:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/35076109.html
匿名

发表评论

匿名网友

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

确定