示例Demo在GitHub:https://github.com/976971956/ChineseSortDemo
在做項目的時候,總遇到排序問題,英文排序是很簡單的,直接使用compare方法就可以實現(xiàn)了,但是一旦遇到中文,就顯得麻煩了。
iOS和java不同,java能進(jìn)行中文字符串的比較,而iOS卻沒有這個功能。于是乎,iOS中的中文排序就要自己想辦法了。相信很多人想到的方法就是獲得中文字符串的拼音,再進(jìn)行排序了。
之前也找過中文排序的相關(guān)文章,想必最出名的就是ChineseString.h和pinyin.c文件(或者其變體)了,對于這個pinyin.c文件里密密麻麻的我表示我沒認(rèn)真看懂~~,自己想著就是中文拼音的對應(yīng)表之類的。但是我使用這兩個文件會出現(xiàn)問題的,排序是有進(jìn)行排序了,但是并不是按照嚴(yán)格的全拼音排序,它只是對中文字符串首字母進(jìn)行了排序,之后的就沒有排了。
在某些場景中,這的確就是足夠了,但是現(xiàn)在我需要的是全拼音排序,就是要對中文字符串整個拼音排序。在對著pinyin.c一大串沒看懂的代碼面前,想著還是自己想辦法弄一個吧。在這個過程中,獲得拼音是第一個難關(guān),之后的通過拼音進(jìn)行排序說到底就是進(jìn)行英文字符串的比較。幸好,最終還是在網(wǎng)上找到獲得中文字符串拼音的方法。
首先總體思路是這樣的:
- 獲得拼音進(jìn)行比較排序是必須的了,排序就意味著存在數(shù)組,但是原本的中文字符串該是如何存儲的呢,應(yīng)該怎樣存在數(shù)組中呢。我自個兒想了三種方式,一是簡單直接的中文字符串?dāng)?shù)組。接著想著有時候需要排序的中文字符串可能還附加其他的屬性,于是有了第二中方式,就是使用字典(NSDictionary)存儲需要排序的中文字符串以及其他屬性。一個例子就是現(xiàn)在需要對通訊錄的人名排序,而通訊錄每個人除了人名,至少還包含電話號碼,那么就要確保按照人名排序完成后,電話號碼也相應(yīng)的進(jìn)行了排序了,那么在這個例子中使用第二種方式就是通訊錄就是一個數(shù)組,而數(shù)組的元素就是字典,字典包含了兩個屬性,一個是人名,另一個是電話號碼。而第三種方式是從第二種方式延伸出來的,還是以通訊錄排序為例子,我可以把通訊錄中每個人都看成一個類的實例(對象),這樣人名和電話號碼就是類中的屬性,這樣的話,通訊錄是一個數(shù)組,而數(shù)組的元素不再是字典,而是一個個類的實例了。
第一種方式數(shù)組初始化Demo:
NSArray *a1 = @[@"張三", @"李三", @"li三", @"qeri三", @"rei三", @"lbcx三", @"kjh三", @"照三", @"于三", @"破三", @"梁三"];
第二種方式數(shù)組初始化Demo:
NSArray *a2 = @[
@{@"name":@"張三", @"num":@"1"},
@{@"name":@"李三", @"num":@"2"},
@{@"name":@"li三", @"num":@"3"},
@{@"name":@"qeri三", @"num":@"4"},
@{@"name":@"rei三", @"num":@"5"},
@{@"name":@"lbcx三", @"num":@"6"},
@{@"name":@"kjh三", @"num":@"7"},
@{@"name":@"照三", @"num":@"8"},
@{@"name":@"于三", @"num":@"9"},
@{@"name":@"破三", @"num":@"10"},
@{@"name":@"梁三", @"num":@"11"}];
第三種方式數(shù)組初始化Demo:(這里說明一下,JHChineseInfo是只有一個屬性(JHChineseString)的類,如果要使用這種方式進(jìn)行排序,自定義的類必須繼承JHChineseInfo,就如下面的SubChineseInfo,這是這種方式的一點限制,如有大神路過,請給點改進(jìn)的意見,謝謝~)
JHChineseInfo *ci1 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci2 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci3 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci4 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci5 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci6 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci7 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci8 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci9 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci10 = [[JHChineseInfo alloc] init];
JHChineseInfo *ci11 = [[JHChineseInfo alloc] init];
ci1.JHChineseString = @"張三";
ci2.JHChineseString = @"李三";
ci3.JHChineseString = @"li三";
ci4.JHChineseString = @"qeri三";
ci5.JHChineseString = @"rei三";
ci6.JHChineseString = @"lbcx三";
ci7.JHChineseString = @"kjh三";
ci8.JHChineseString = @"照三";
ci9.JHChineseString = @"于三";
ci10.JHChineseString = @"破三";
ci11.JHChineseString = @"梁三";
NSArray *a3 = @[ci1, ci2, ci3, ci4, ci5, ci6, ci7, ci8, ci9, ci10, ci11];
或者:
SubChineseInfo *sci1 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci2 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci3 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci4 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci5 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci6 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci7 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci8 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci9 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci10 = [[SubChineseInfo alloc] init];
SubChineseInfo *sci11 = [[SubChineseInfo alloc] init];
sci1.JHChineseString = @"張三";
sci1.num = @"1";
sci2.JHChineseString = @"李三";
sci2.num = @"2";
sci3.JHChineseString = @"li三";
sci3.num = @"3";
sci4.JHChineseString = @"qeri三";
sci4.num = @"4";
sci5.JHChineseString = @"rei三";
sci5.num = @"5";
sci6.JHChineseString = @"lbcx三";
sci6.num = @"6";
sci7.JHChineseString = @"kjh三";
sci7.num = @"7";
sci8.JHChineseString = @"照三";
sci8.num = @"8";
sci9.JHChineseString = @"于三";
sci9.num = @"9";
sci10.JHChineseString = @"破三";
sci10.num = @"10";
sci11.JHChineseString = @"梁三";
sci11.num = @"11";
NSArray *a4 = @[sci1, sci2, sci3, sci4, sci5, sci6, sci7, sci8, sci9, sci10, sci11];
-
獲得中文字符串的拼音
函數(shù)- (NSString) chineseStringTransformPinyin: (NSString)chineseString// 拼音字段
NSMutableString *tempNamePinyin = [chineseString mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)tempNamePinyin, NULL, kCFStringTransformMandarinLatin, NO);
CFStringTransform((__bridge CFMutableStringRef)tempNamePinyin, NULL, kCFStringTransformStripDiacritics, NO);
這個方法就是從萬能的網(wǎng)上尋找回來的,具體說明的話當(dāng)時看看了,沒記錄網(wǎng)址就忘了。現(xiàn)在自己產(chǎn)生了一個問題,不知這個方法在效率上是否最優(yōu),還有沒有更好的方法。在此再請路過的大神知道的指點一下~~ 這一步就開始進(jìn)行中文排序了,上述的三種方式分別對應(yīng)了三個方法:
1)- (NSArray) chineseSortWithStringArray: (NSArray)stringArray;
stringArray必定要是字符串?dāng)?shù)組,就是數(shù)組的元素就是需要排序的中文字符串
2)- (NSArray) chineseSortWithDictionaryArray: (NSArray)dictionaryArray andFieldKey: (NSString*)fieldKey
dictionaryArray是字典數(shù)組,就是數(shù)組的元素是字典,其中key值為fieldKey對應(yīng)的值就是需要排序的中文字符串
3)- (NSArray) chineseSortWithObjectArray: (NSArray)objectArray
objectArray是對象數(shù)組,就是數(shù)組的元素一定要是JHChineseInfo或者其子類(一般如需自定義就自定義一個子類出來,把需要排序的中文字符串字段賦給JHChineseString屬性即可)
排序關(guān)鍵代碼(其實就是通過pinyin字段進(jìn)行英文字符串比較獲得排序結(jié)果):
[tempArray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [[obj1 objectForKey:@"pinyin"] compare:[obj2 objectForKey:@"pinyin"]];
}];
最終返回結(jié)果。
4.使用規(guī)則
可自定義模型繼承JHChineseInfo,可先將字典轉(zhuǎn)模型,在循環(huán)給name,num賦值。也可將JHChineseInfo中name改名字,但JHChineseSort中所有name都要改。
我把獲得拼音以及三種方式的函數(shù)獨立出來了,在使用的時候只需要導(dǎo)入JHChineseSort.h、JHChineseSort.m、JHChineseInfo.h、JHChineseInfo.m以及 筆畫文件 KLChineseCharactersTool.h、KLChineseCharactersTool.m、Chinese.json、byteNum.json。