字符串比较中NSNumericSearch选项的工作原理

栏目: Objective-C · 发布时间: 5年前

内容简介:相信研究过怎么在 ObjC 中进行版本字符串比对的朋友,大多都看过这一篇 StackOverflow 的问答:里面提到的

相信研究过怎么在 ObjC 中进行版本字符串比对的朋友,大多都看过这一篇 StackOverflow 的问答:

Compare version numbers in Objective-C

里面提到的 [versionStrA compare:versionStrB options:NSNumericSearch] 的方案应该是最优雅的方案了。

但是不理解这个 NSNumericSearch 的具体工作原理就去盲目使用是危险的,今天我就来研究下它的具体工作原理。

官方文档

参照 官方文档 里的说明:

Numbers within strings are compared using numeric value, that is,
Name2.txt < Name7.txt < Name25.txt.

Numeric comparison only applies to the numerals in the string, not other characters that
would have meaning in a numeric representation such as a negative sign, a comma, or a
decimal point.

粗略的直译一下:

在字符串中的数字将被用数值进行比较,就是说,Name2.txt < Name7.txt < Name25.txt。

数值比较仅仅对字符串中的纯数字(0-9)生效,而不对其它在数字表达中含有意义的字符生效,例如负号,逗号或小数点。

这段说明略有歧义,导致很多人第一次看的时候被绕晕。例如刚刚那篇 StackOverflow 问答里的 dooleyo 就理解成 "1.2.3""1.1.12" 进行比较时,会抛弃所有非数字的字符变成 1231112 进行比较,最后得到 "1.2.3" < "1.1.12" 的结论。问答里不少其它朋友也有类似的想法。

探求真相

真相只有经过实验才能得到,所以写了一些测试代码来试一下具体的结果:

- (void)testExample {
    [self compareString:@"1.2.3" andString:@"1.1.12"];
    [self compareString:@"1.8" andString:@"1.7.2.3.55"];
    [self compareString:@"1.44" andString:@"1.5"];
    [self compareString:@"7.4.1" andString:@"7.5"];
}
    
- (void)compareString:(NSString *)stringA andString:(NSString *)stringB {
    NSComparisonResult result = [stringA compare:stringB options:NSNumericSearch];
    switch (result) {
        case NSOrderedDescending:
            NSLog(@"%@ > %@", stringA, stringB);
            break;
        case NSOrderedAscending:
            NSLog(@"%@ < %@", stringA, stringB);
            break;
        default:
            NSLog(@"%@ = %@", stringA, stringB);
            break;
    }
}

得到的结果是:

1.2.3 > 1.1.12
1.8 > 1.7.2.3.55
1.44 > 1.5
7.4.1 < 7.5

看上去结果都是正确的,那么看来 NSNumericSearch 并不是粗暴的去掉所有非数字字符后进行数值比对。

结合原回答里答主说的一句话: keeping in mind that "1" < "1.0" < "1.0.0" ,忽然想到了一些什么,继续进行下一步的实验,得到的结果如下:

1 < 1.0
1.0 < 1.0.0
a10 < b2
a2 < b10
c10 > b2
c2 > b10
2a < 10b
10a > 2b
2c < 10b
10c > 2b

大家看到这里应该可以猜到官方文档的意思是什么了,其实文档的意思是整个字串 非数字的部分仍然进行常规的字符比较逻辑,只有在遇到数字的时候会把连续的数字转换成数值再进行比对 。具体的比较过程示例参照下图:

字符串比较中NSNumericSearch选项的工作原理

这时候一些奇特的比对结果就可以解释明白了,比如使用这种比较模式会得出 "01" = "1"

继续深入

那么还剩下一个问题,如果和数字字符比较的是非数字字符,会怎么样?我们可以挑一些 ASCII 码在数字字符周围的字符进行试验,结果如下:

a/c < a100c
a:c > a100c
a/c < a1c
a:c > a1c

注意这里出现的部分字符 ASCII 码为:

/ = 47
0 = 48
1 = 49
...
9 = 57
: = 58

可以看出现了比较的字符一边是数字,一边是非数字时,是按照常规的 ASCII 码进行比对的。

总结

那么分析到这里就基本结束了,剩下的一些场景类推一下都很容易理解。

其实在各大 OS 里的文件系统下文件 排序 用的就是这种比较方法,一开始没有想到这点所以理解上绕了一些弯路。

NSNumericSearch 来进行版本字符串的比对也是十分有效的,不是特殊需要的话就再也不用傻傻的自己分割字符串再分段比较啦。


以上所述就是小编给大家介绍的《字符串比较中NSNumericSearch选项的工作原理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ruby Cookbook

Ruby Cookbook

Lucas Carlson、Leonard Richardson / O'Reilly Media / 2006-7-29 / USD 49.99

Do you want to push Ruby to its limits? The "Ruby Cookbook" is the most comprehensive problem-solving guide to today's hottest programming language. It gives you hundreds of solutions to real-world pr......一起来看看 《Ruby Cookbook》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具