字符串比较中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选项的工作原理》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

C++数值算法(第二版)

C++数值算法(第二版)

William T.Vetterling、Brian P.Flannery、Saul A.Teukolsky / 胡健伟、赵志勇、薛运华 / 电子工业出版社 / 2005年01月 / 68.00

本书选材内容丰富,除了通常数值方法课程的内容外,还包含当代科学计算大量用到的专题,如求特殊函数值、随机数、排序、最优化、快速傅里叶变换、谱分析、小波变换、统计描述和数据建模、常微分方程和偏微分方程数值解、若干编码算法和任意精度的计算等。 本书科学性和实用性统一。每个专题中,不仅对每种算法给出了数学分析和比较,而且根据作者的经验对算法做出了评论和建议,并在此基础上给出了用C++语言编写的实用程......一起来看看 《C++数值算法(第二版)》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具