sitiveSearch结合起来就是例如"aaa" > "AAA"
并且指定了当前的区域locale作为参数,这就相当于指定使用CLDR进行排序,如果是在手机上,这个方法的调用和系统当前的区域设置是有很大关系的,这和我们代码中设置locale是一个道理。我们可以这样理解,调用这个方法得到的结果和在iOS Files中文件名选择按照名称排序得到的结果是一样的。在iOS中,当我们的区域设置为中国时,排序顺序就是 标点符号等特殊符号>数字>中文>英文等其他
。
区域设置成中文后的排序
自此,对localizedStandardCompare:
的使用,大家应该比较清楚了。
数字的比较
这里单独把数字字符串的比较列出来,是因为一些人对这里比较迷惑。由于localizedStandardCompare:
中有使用NSNumericSearch
选项,这里简单来说,就是假如目前两个字符串是相等的,两者都出现了数字,则分别从两者种取出这段数字进行数字化来比较大小,按照数字大小排序。为了验证这里的逻辑,我看了下CFString.c中CFStringCompareWithOptionsAndLocale
这个方法的实现,这个就是compare
实际调用的的比较方法。其中关于数字大小比较的代码如下:
if (numerically && ((0 == strBuf1Len) && (str1Char <= '9') && (str1Char >= '0')) && ((0 == strBuf2Len) && (str2Char <= '9') && (str2Char >= '0'))) { // If both are not ASCII digits, then don't do numerical comparison here
uint64_t intValue1 = 0, intValue2 = 0; // !!! Doesn't work if numbers are > max uint64_t
CFIndex str1NumRangeIndex = str1Index;
CFIndex str2NumRangeIndex = str2Index;
do {
intValue1 = (intValue1 * 10) + (str1Char - '0');
str1Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf1, ++str1Index);
} while ((str1Char <= '9') && (str1Char >= '0'));
do {
intValue2 = intValue2 * 10 + (str2Char - '0');
str2Char = CFStringGetCharacterFromInlineBuffer(&inlineBuf2, ++str2Index);
} while ((str2Char <= '9') && (str2Char >= '0'));
if (intValue1 == intValue2) {
if (forceOrdering && (kCFCompareEqualTo == compareResult) && ((str1Index - str1NumRangeIndex) != (str2Index - str2NumRangeIndex))) {
compareResult = (((str1Index - str1NumRangeIndex) < (str2Index - str2NumRangeIndex)) ? kCFCompareLessThan : kCFCompareGreaterThan);
numericEquivalence = true;
forcedIndex1 = str1NumRangeIndex;
forcedIndex2 = str2NumRangeIndex;
}
continue;
} else if (intValue1 < intValue2) {
if (freeLocale && locale) {
CFRelease(locale);
}
return kCFCompareLessThan;
} else {
if (freeLocale && locale) {
CFRelease(locale);
}
return kCFCompareGreaterThan;
}
}
这段代码的含义就是,如果两个字符串都是以数字开始(也可能是字符串前面都相等,当前从数字部分开始比较),则取出两个字符串的数字,按照数字大小进行对比。如果数字能够比较出大小,则直接返回两个字符串的大小关系,不再对后面的字符串进行对比。比如“0123aaa” 和“1bbbbbbbbb”,就直接返回“0123aaa”大于“1bbbbbbbbb”。当然,这里取出的数字可能超出了uint64_t表示的最大值,但是这种概率很低,在我们的名称排序中,很难遇到这么长的数字进行比较的。明白这个规则后,大家对字符串中出现的数字在进行排序时应该比较理解了。下面的名字排序是对着的。
综述
本文主要讲述由localizedStandardCompare:
这个苹果系统方法所引发的对排序规则的深入研究,简单来说,设置中选择区域为中国时,排序顺序为 标点符号等特殊符号>数字>中文>英文等其他
。中文本身是按照pinyin排序的,只是由于多音字的关系,不能够做到100%按照中文习惯来排序,会有些无法正确排序的问题,但大体已经符合我们的习惯了。
参考
https://zh.wikipedia.org/wiki/Unicode
https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFStrings/Articles/UnicodeBasis.html
https://www.objc.io/issues/9-strings/unicode/
http://unicode.org/reports/tr10/
https://www.cnblogs.com/huahuahu/p/Unicode-zi-fu-chuan-pai-xu-gui-ze-yi-ru-he-que-din.html
https://raw.githubusercontent.com/larvit/larvitgeodata/master/cldrData/common/uca/allkeys_CLDR.txt
http://cldr.unicode.org/
相关阅读
【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识
此文已由作者授权腾讯云+社区发布,更多原文请点击
搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!
海量技术实践经验,尽在云加社区!