我正在尝试比较和检查版本号,但无法使用任何比较运算符,因为可能的示例是
2.0
3.1a
2.1c
3.11d
有什么建议么?
答案1
这个问题看似复杂,实则复杂。我将列出一些组成因素来说明必须考虑哪些因素。解决方案使用一个辅助列,其中包含可以正确排序或评估的版本号翻译。下图仅用于解释目的,实际解决方案在最后。
A 列是版本号列表。请注意,末尾没有字母的版本可以解释为数字。除非版本转换为整数,否则这不一定是个问题。例如,版本 2.0 可能最终被简单地表示为2
,在这种情况下,解决方案必须更复杂才能提供比较值的方法。此解决方案从所有版本名称都存储为文本的前提开始。
版本号和子号通常为两位数。这意味着不能仅通过版本字符串中的字符位置来解析版本的组成部分。
这也意味着子编号无法通过正常方式排序。此示例包括版本 3.7 和 3.11。正常排序会认为 3.7 是较高的编号,但 3.11 实际上是较新的版本。
当然,还有引发问题的议题——以字母结尾的版本;如何对数字和字母的混合进行排序。
将问题分解开来,我在这个例子中包含了所需的组件,以便于理解。每个组件都很简单,但将它们组合成一个公式就很难理解了。
小数位置
解析版本号从小数点所在的位置开始。如果只能有一位数的主版本号,则该版本号始终位于版本字符串中的第 2 位。如果版本可以输入两位数,则 B 列中的以下公式将执行此操作:
=FIND(".",A2)
小数点左边的部分
小数点左边的部分需要与右边的部分分开处理。由于版本可以包含字母,我们不能只取整数。小数点的位置可用于剥离整数部分(示例中的 C 列):
=LEFT(A2,B2-1)
子版本号
解析子版本号取决于末尾是否有字母。这是 D 列,通过以下方式找到:
=CODE(RIGHT(A2,1))>57
这将使用 ASCII 代码来评估最后一个字符。数字以 ASCII 字符 57 结束,因此版本标识中使用的任何更高字符都将是字母。
E列显示解析子版本号:
=MID(A2,B2+1,LEN(A2)-B2-D2)
它取字符串的中间部分,从小数点后的字符开始,长度等于整个字符串的长度减去小数点部分,并可能减去末尾的字符。对于末尾的字符,它使用布尔值(0
或1
)来判断它是否以字母结尾。
需要通过为一位数值添加填充零来将子版本号表示为统一的位数。通常使用 TEXT 函数来实现这一点。但是,至少在 LO Calc 中,对于零值,此方法无法正常工作。因此,列 F 中使用的公式为:
=REPT("0",2-LEN(A2)+B2+D2)&E2
这将创建“缺失位置”数量的重复0
,然后连接上一步中的子版本号。
结束信
为了对版本号进行排序,末尾的任何字母都会转换为其 ASCII 代码(如果没有字母,则会添加填充值零 ASCII 48 作为占位符。我使用它而不是 ASCII 00,因为 ASCII 数字可以是三位数,并且必须用两位数代码的前导零填充。与子版本号一样,这会使事情变得复杂。G 列中填充的最后一个字符的公式:
=TEXT(IF(CODE(RIGHT(A2,1))>57,CODE(RIGHT(A2,1)),48),"0##")
在这种情况下,可以使用TEXT函数来添加填充零。
可排序的值
排序值由 H 列中的以下组件构成:
=VALUE(C2&F2&G2)
这将连接这三个部分,然后将结果转换为数字。只需一步即可完成此操作,方法是用单元格公式替换单元格引用,这将为您提供以下辅助列公式:
=VALUE(LEFT(A2,FIND(".",A2)-1)&REPT("0",2-LEN(A2)+FIND(".",A2)+(CODE(RIGHT(A2,1))>57))&MID(A2,FIND(".",A2)+1,LEN(A2)-FIND(".",A2)-(CODE(RIGHT(A2,1))>57))&TEXT(IF(CODE(RIGHT(A2,1))>57,CODE(RIGHT(A2,1)),48),"0##"))
解决方案
解决方案如下:
查找最新版本
您只需对辅助列进行排序,最高版本将位于列表末尾。或者,您可以进行查找以将结果发布到单元格。H9 中的公式:
=INDEX(A2:A7,MATCH(MAX(H2:H7),H2:H7,0))
这将定位辅助列中的最大值并显示同一行的版本号。
为了说明这不仅仅是选择最后一个值,下面是包含原始数据和版本 3.7 的示例,其中版本 3.11d 埋在中间: