同时按照行长度和字母顺序排序字符串数组

4

我看到在其他语言中也提出了这个问题,并得到了很好的回答。例如:

如何按行长度排序文件,然后按第二关键字按字母顺序排序?

如何按字符串长度排序,然后按字母顺序排序?

如何按字母顺序和长度排序字符串?

我在Golang中想不出怎么做 :/ 假设我有以下列表:

2 22 2H 2J 2J2 2J3 2J322422 2J322423 2J33 2M 2P 2W 2X

我希望输出的结果是排序后的:
2 22 2H 2J 2M 2P 2W 2X 2J2 2J3 2J33 2J322422 2J322423

我尝试了一些Golang的东西,但就是无法让它正常运转。

// Log
t.Log.Println(values)

// Sort values alphabetically
sort.Strings(values)

// Sort values by length
sort.Slice(values, func(i, j int) bool {
    return len(values[i]) < len(values[j])
})

// Log
t.Log.Println(values)
2个回答

6

如果你进行了两次排序,第二次排序将不考虑第一次排序的规则。

你必须进行一次排序,排序规则必须包括所有想要排序的属性。

所以,首先你想按长度排序。如果两个元素长度相同,则按自然顺序排序。你可以通过在 less() 函数中首先检查长度来实现这一点。如果它们不相等,则按长度的顺序决定结果。如果它们相等,则按自然顺序排序。

list := strings.Split("2 22 2H 2J 2J2 2J3 2J322422 2J322423 2J33 2M 2P 2W 2X", " ")
fmt.Println(list)

sort.Slice(list, func(i, j int) bool {
    l1, l2 := len(list[i]), len(list[j])
    if l1 != l2 {
        return l1 < l2
    }
    return list[i] < list[j]
})
fmt.Println(list)

这将输出以下结果(在Go Playground上尝试一下):
[2 22 2H 2J 2J2 2J3 2J322422 2J322423 2J33 2M 2P 2W 2X]
[2 22 2H 2J 2M 2P 2W 2X 2J2 2J3 2J33 2J322422 2J322423]

你可以将此逻辑扩展到按任意数量的属性(或规则)进行排序。你首先检查高优先级规则,如果它们定义了顺序差异,则返回由它们指定的顺序(即第 i 个元素是否小于第 j 个元素)。如果它们不区分要素的位置,则继续使用较低优先级规则。

1
太好了,谢谢。这帮助我更好地理解排序包的工作方式。 - James

2
你需要一个比较器函数,根据你定义的排序规则进行适当的比较。
要对字符串切片进行按长度和字母顺序排序,类似以下代码即可:
strs := []string{
  "Zulu"    , "Yankee" , "X-Ray"  , "Whiskey" , "Victor" ,
  "Ulysses" , "Tango"  , "Sierra" , "Romeo"   , "Quebec" ,
  "Poppa"   ,"Oscar"   , "Nancy"  , "Mike"    , "Lima"   ,
  "Kilo"    , "Juliet" , "India"  , "Hotel"   , "Golf"   ,
  "Foxtrot" , "Echo"   , "Delta"  , "Charlie" , "Bravo"  ,
  "Alpha"   ,
  }

  byLengthThenAlphabetically := func(i int, j int) bool {
    x := strs[i]
    y := strs[j]
    deltaLength := len(x) - len(y)

    return deltaLength < 0 || (deltaLength == 0 && x < y)
  }
  
  sort.Slice(strs, byLengthThenAlphabetically )

在Go Playground中尝试一下:https://play.golang.org/p/nL2bTDlWM49


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接