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

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

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比较整个字符串,可以比较单个符文。

  1. type ByCase []string
  2. func (s ByCase) Len() int { return len(s) }
  3. func (s ByCase) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  4. func (s ByCase) Less(i, j int) bool {
  5. iRunes := []rune(s[i])
  6. jRunes := []rune(s[j])
  7. max := len(iRunes)
  8. if max > len(jRunes) {
  9. max = len(jRunes)
  10. }
  11. for idx := 0; idx < max; idx++ {
  12. ir := iRunes[idx]
  13. jr := jRunes[idx]
  14. lir := unicode.ToLower(ir)
  15. ljr := unicode.ToLower(jr)
  16. if lir != ljr {
  17. return lir < ljr
  18. }
  19. // the lowercase runes are the same, so compare the original
  20. if ir != jr {
  21. return ir < jr
  22. }
  23. }
  24. // 如果字符串在最短字符串的长度范围内相同,则较短的字符串排在前面
  25. return len(iRunes) < len(jRunes)
  26. }

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

英文:

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

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

  1. type ByCase []string
  2. func (s ByCase) Len() int { return len(s) }
  3. func (s ByCase) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  4. func (s ByCase) Less(i, j int) bool {
  5. iRunes := []rune(s[i])
  6. jRunes := []rune(s[j])
  7. max := len(iRunes)
  8. if max &gt; len(jRunes) {
  9. max = len(jRunes)
  10. }
  11. for idx := 0; idx &lt; max; idx++ {
  12. ir := iRunes[idx]
  13. jr := jRunes[idx]
  14. lir := unicode.ToLower(ir)
  15. ljr := unicode.ToLower(jr)
  16. if lir != ljr {
  17. return lir &lt; ljr
  18. }
  19. // the lowercase runes are the same, so compare the original
  20. if ir != jr {
  21. return ir &lt; jr
  22. }
  23. }
  24. // If the strings are the same up to the length of the shortest string,
  25. // the shorter string comes first
  26. return len(iRunes) &lt; len(jRunes)
  27. }

答案2

得分: 5

这可能是一个解决方案:

  1. package main
  2. import (
  3. "strings"
  4. "sort"
  5. "fmt"
  6. )
  7. var listOfStrings []string = []string{
  8. "mars bar",
  9. "milk-duds",
  10. "Mars bar",
  11. "milk",
  12. "milky-way",
  13. "Milk",
  14. "Milky-way",
  15. "mars",
  16. }
  17. type Alphabetic []string
  18. func (list Alphabetic) Len() int { return len(list) }
  19. func (list Alphabetic) Swap(i, j int) { list[i], list[j] = list[j], list[i] }
  20. func (list Alphabetic) Less(i, j int) bool {
  21. var si string = list[i]
  22. var sj string = list[j]
  23. var si_lower = strings.ToLower(si)
  24. var sj_lower = strings.ToLower(sj)
  25. if si_lower == sj_lower {
  26. return si < sj
  27. }
  28. return si_lower < sj_lower
  29. }
  30. func main() {
  31. fmt.Println("UNSORTED")
  32. printStrings(listOfStrings)
  33. sort.Sort(Alphabetic(listOfStrings))
  34. fmt.Println()
  35. fmt.Println("SORTED ALPHABETICALLY")
  36. printStrings(listOfStrings)
  37. }
  38. func printStrings(slice []string) {
  39. for i := 0; i < len(slice); i++ {
  40. fmt.Println(slice[i])
  41. }
  42. }

以下是输出结果:

  1. UNSORTED
  2. mars bar
  3. milk-duds
  4. Mars bar
  5. milk
  6. milky-way
  7. Milk
  8. Milky-way
  9. mars
  10. SORTED ALPHABETICALLY
  11. mars
  12. Mars bar
  13. mars bar
  14. Milk
  15. milk
  16. milk-duds
  17. Milky-way
  18. milky-way
英文:

This may be a solution:

  1. package main
  2. import (
  3. &quot;strings&quot;
  4. &quot;sort&quot;
  5. &quot;fmt&quot;
  6. )
  7. var listOfStrings []string = []string{
  8. &quot;mars bar&quot;,
  9. &quot;milk-duds&quot;,
  10. &quot;Mars bar&quot;,
  11. &quot;milk&quot;,
  12. &quot;milky-way&quot;,
  13. &quot;Milk&quot;,
  14. &quot;Milky-way&quot;,
  15. &quot;mars&quot;,
  16. }
  17. type Alphabetic []string
  18. func (list Alphabetic) Len() int { return len(list) }
  19. func (list Alphabetic) Swap(i, j int) { list[i], list[j] = list[j], list[i] }
  20. func (list Alphabetic) Less(i, j int) bool {
  21. var si string = list[i]
  22. var sj string = list[j]
  23. var si_lower = strings.ToLower(si)
  24. var sj_lower = strings.ToLower(sj)
  25. if si_lower == sj_lower {
  26. return si &lt; sj
  27. }
  28. return si_lower &lt; sj_lower
  29. }
  30. func main() {
  31. fmt.Println(&quot;UNSORTED&quot;)
  32. printStrings(listOfStrings)
  33. sort.Sort(Alphabetic(listOfStrings))
  34. fmt.Println()
  35. fmt.Println(&quot;SORTED ALPHABETICALLY&quot;)
  36. printStrings(listOfStrings)
  37. }
  38. func printStrings(slice []string) {
  39. for i := 0; i &lt; len(slice); i++ {
  40. fmt.Println(slice[i])
  41. }
  42. }

Here's the output:

  1. UNSORTED
  2. mars bar
  3. milk-duds
  4. Mars bar
  5. milk
  6. milky-way
  7. Milk
  8. Milky-way
  9. mars
  10. SORTED ALPHABETICALLY
  11. mars
  12. Mars bar
  13. mars bar
  14. Milk
  15. milk
  16. milk-duds
  17. Milky-way
  18. milky-way

答案3

得分: 1

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

  1. package main
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. "unicode"
  7. )
  8. type slice struct { sort.StringSlice }
  9. func (s slice) Less(d, e int) bool {
  10. t := strings.Map(unicode.ToUpper, s.StringSlice[d])
  11. u := strings.Map(unicode.ToUpper, s.StringSlice[e])
  12. return t < u
  13. }
  14. func main() {
  15. a := slice{
  16. sort.StringSlice{"a", "b", "A", "B"},
  17. }
  18. sort.Sort(a)
  19. fmt.Println(a.StringSlice) // [a A b B]
  20. }

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

英文:

Heres a Unicode friendly method that utilizes strings.Map:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;sort&quot;
  5. &quot;strings&quot;
  6. &quot;unicode&quot;
  7. )
  8. type slice struct { sort.StringSlice }
  9. func (s slice) Less(d, e int) bool {
  10. t := strings.Map(unicode.ToUpper, s.StringSlice[d])
  11. u := strings.Map(unicode.ToUpper, s.StringSlice[e])
  12. return t &lt; u
  13. }
  14. func main() {
  15. a := slice{
  16. sort.StringSlice{&quot;a&quot;, &quot;b&quot;, &quot;A&quot;, &quot;B&quot;},
  17. }
  18. sort.Sort(a)
  19. fmt.Println(a.StringSlice) // [a A b B]
  20. }

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:

确定