广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Go语言实现有规律的数字版本号的排序工具
  • 587
分享到

Go语言实现有规律的数字版本号的排序工具

Go语言实现排序工具Go语言排序工具Go语言排序 2023-01-10 09:01:25 587人浏览 安东尼
摘要

目录前言创作解读版本号的大小比较与排序版本号的合法性校验错误处理总结前言 在某些场景,我们可能需要对版本号进行排序。版本号的形式有很多种,例如: 1.0.0, 1.0.1.1, 2.

前言

在某些场景,我们可能需要对版本号进行排序。版本号的形式有很多种,例如:

  • 1.0.0, 1.0.1.1, 2.0.1.1
  • v1.0.0, v1.10.1, v2.0
  • ······

而本文所介绍的版本号排序工具,是针对有规律的数字版本号如 1.0.0, 1, 2.15.0 这种形式。

创作解读

版本号的大小比较与排序

版本号排序的前提,首先得比较两个版本号的大小。由于版本号长度可能不一致,所以需要额外做一些处理。对于版本号的比较,我的算法思路是:

1、以 . 为分隔符,将版本号的每段数字存到切片里,方便后续比较大小。例如 "1.0"["1", "0"]"1.0.1"["1", "0", "1"]

firstVersions := strings.Split(versions[i], ".")
secondVersions := strings.Split(versions[j], ".")

2、由于两个版本号的长度可能不一致,因此需要做 填充0,统一长度 的操作。所以第二步就是获取两个版本号中,最大长度,然后对长度最小的版本号切片,填充零,保持两个版本号的长度一致。例如第一步的两个版本号 ["1", "0"]["1", "0", "1"],需要对第一个版本号填充一个零(填充之后的结果 → ["1", "0", "0"]),才能保持两个版本号的长度一致,方便后续比较。

// 0 填充
// 获取最大长度并向最小长度的切片填充 "0",统一长度
func getMaxAndFillZero(s1 *[]string, s2 *[]string) int {
    len1, len2 := len(*s1), len(*s2)
    if len1 > len2 {
        fillZero(s2, len1-len2)
        return len1
    }
    fillZero(s1, len2-len1)
    return len2
}

// 0 填充
func fillZero(s *[]string, size int) {
    for i := 0; i < size; i++ {
        *s = append(*s, "0")
    }
}

size 为最大长度 - 最小长度的值,也就是要填充 0 的个数。

3、遍历切片,从前依次比较两个版本号每段数字的大小。

如果第一个版本号的第一段数字大于或小于第二个版本号的第二段数字,则可以根据排序规则决定两个版本号的先后位置。

如果相等,则比较下一段数字的大小,以此类推。

for k := 0; k < maxLen; k++ {
    // 由于上面判断了版本号的合法性,因此 error 可以忽略
    vi, _ := strconv.Atoi(firstVersions[k])
    vj, _ := strconv.Atoi(secondVersions[k])
    if vi < vj {
        if sortRule == DESC {
            // 降序排序
            // todo 交换操作
        }
        // 默认升序排序,即使 sortRule 不是 ASC
        // todo 交换操作
    } else if vi > vj {
        // 降序排序
        if sortRule == DESC {
            // todo 交换操作
        }
        // 默认升序排序,即使 sortRule 不是 ASC
        // todo 交换操作
    }
}

字符串切片的排序,本工具使用的函数是 SliceStable(x any, less func(i, j int) bool),通过此函数,可以自定义比较大小的规则。

sort.SliceStable(versions, func(i, j int) bool {
    firstVersions := strings.Split(versions[i], ".")
    secondVersions := strings.Split(versions[j], ".")
    // 判断版本号格式的合法性
    isNORMal(firstVersions)
    isNormal(secondVersions)
    // 获取最大值并填充 "0", 统一长度
    maxLen := getMaxAndFillZero(&firstVersions, &secondVersions)
    for k := 0; k < maxLen; k++ {
        // 由于上面判断了版本号的合法性,因此 error 可以忽略
        vi, _ := strconv.Atoi(firstVersions[k])
        vj, _ := strconv.Atoi(secondVersions[k])
        if vi < vj {
            if sortRule == DESC {
                // 降序排序
                return false
            }
            // 默认升序排序,即使 sortRule 不是 ASC
            return true
        } else if vi > vj {
            // 降序排序
            if sortRule == DESC {
                return true
            }
            // 默认升序排序,即使 sortRule 不是 ASC
            return false
        }
    }
    return false
})

版本号的合法性校验

由于本工具处理的版本号是有规律的数字版本号,如果版本号包含字母或其他特殊字符,会影响到排序的进行,因此需要提前对版本号进行合法性的校验。

// 判断版本号的格式是否合法
func isNormal(versions []string) {
   for _, v := range versions {
      for _, r := range []rune(v) {
         if !unicode.IsNumber(r) {
            panic(errors.New("版本号格式错误:" + string(r)))
         }
      }
   }
}

遍历每段版本号,然后对每段版本号的字符进行遍历,判断是否是数字,如果不是,则 panic 掉,结束排序。

错误处理

由于版本号的不合法性,可能会程序运行的过程中产生错误。因此,有必要人工捕获错误,提高工具的健壮性。

版本号排序函数提供一个 error 的返回值,用于判断是否产生错误。错误的捕获逻辑如下:

defer func() {
   if r := recover(); r != nil {
      if er, ok := r.(error); ok {
         err = er
      } else {
         err = errors.New("")
         fmt.Println("未知错误: ")
         fmt.Println(r)
      }
   }
}()

捕获版本号的合法性校验时主动 panic 的错误,并结束排序。

总结

  • 本工具实现了对有规律的数字版本号集合进行排序。
  • 在排序的过程中,由于版本号的长度可能不一致,因此执行填充 0 操作,统一长度,再进行版本号的大小比较;
  • 除此之外,还对版本号的合法性做了校验,捕获可预知和不可预知的 panic 错误,提高了工具的健壮性。
  • 测试,核心功能已实现,但有些地方还能改进,后续会对代码进行优化

到此这篇关于Go语言实现有规律的数字版本号的排序工具的文章就介绍到这了,更多相关Go语言排序工具内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: Go语言实现有规律的数字版本号的排序工具

本文链接: https://www.lsjlt.com/news/177236.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作