在我的应用程序中,我有一个50k +联系人的数据库。要在列表视图上显示它们,我需要计算索引部分标题以在右侧显示它们。
然而,我的逻辑是花费大约3-6秒的时间来准备数据源。
-(NSArray *)getSectionTitleBasedOn:(NSString*)sortBy{
for (RealmContact *contact in contactSource){
if (contact.firstName.length>0) {
if ([sortBy isEqualToString:@"FirstName"]) {
NSString *firName= [contact.firstName stringByReplacingOccurrencesOfString:@" " withString:@""];
NSString *regex = @"^[A-Za-z]+";
NSPredicate *test = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
BOOL result = [test evaluateWithObject:firName];
if (contact.firstName.length>0 && result)
{
[nameDic setObject:@"firstletter" forKey:[[contact.firstName substringToIndex:1]uppercaseString]];
}else{
[nameDic setObject:@"firstletter" forKey:@"#"];
}
}
if ([sortBy isEqualToString:@"LastName"]) {
//same
}
if ([sortBy isEqualToString:@"Company"]) {
//same
}
}
}
NSLog(@"dic %@",nameDic);
return [[nameDic allKeys]sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}
我想知道我能做些什么来改善这一点。
NSString *firName= [contact.firstName stringByReplacingOccurrencesOfString:@" " withString:@""];
NSString *regex = @"^[A-Za-z]+";
NSPredicate *test = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
BOOL result = [test evaluateWithObject:firName];
我这样做是为了检查字符串是否包含特殊字符或无效字符。
获取数组后,我对其进行排序并返回数组。输出将是:
dic {
"#" = firstletter;
A = firstletter;
B = firstletter;
C = firstletter;
D = firstletter;
E = firstletter;
F = firstletter;
G = firstletter;
H = firstletter;
I = firstletter;
J = firstletter;
K = firstletter;
L = firstletter;
M = firstletter;
N = firstletter;
O = firstletter;
P = firstletter;
Q = firstletter;
R = firstletter;
S = firstletter;
T = firstletter;
U = firstletter;
V = firstletter;
W = firstletter;
X = firstletter;
Y = firstletter;
Z = firstletter;
}
答案 0 :(得分:1)
我这样做了:
NSArray *sortedLetters = nil;
NSMutableSet *set = [[NSMutableSet alloc] init];
NSCharacterSet *charSet = [NSCharacterSet characterSetWithCharactersInString:@"AZERTYUIOPQSDFGHJKLMWXCVBN"];
for (RealmContact *contact in _dataSource)
{
NSString *firName = [[contact firstName] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([firName length])
{
unichar c = [[firName uppercaseString] characterAtIndex:0];
if ([charSet characterIsMember:c])
{
[set addObject:[NSString stringWithFormat: @"%C", c]];
}
else
{
[set addObject:@"#"];
}
}
}
sortedLetters = [[set allObjects] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
有什么区别?
•我使用NSSet
而不是NSDictionary
来表示首字母的单一性。我发现无用的NSDictionary
使用未使用的值,只是为了键的唯一性
•我使用stringByTrimmingCharactersInSet:
代替stringByReplacingOccurrencesOfString:withString:
。从理论上讲,stringByTrimmingCharactersInSet:
的代码应该停在第一个不属于集合的字符处,而不是像stringByReplacingOccurrencesOfString:withString:
那样继续到字符串结尾。
•我猜characterIsMember:
比正则表达式/谓词更快
•由于您只对大写感兴趣,因此我在进行测试之前对其进行了翻译,而不是之后,这也可以加速您的谓词。
此外,代码上的小错误:
if (contact.firstName.length>0 && result)
和
[nameDic setObject:@"firstletter" forKey:[[contact.firstName substringToIndex:1]uppercaseString]];
应使用firName
代替contact.firstName
。
在this test sample上,我的解决方案似乎比你的更快(x10)。 我在OS X App(不是iOS)上快速测试。我没有做过很多测试,但值得一试。
我不知道它是否只针对这个问题,但是,你可以做的代码优化:
NSString *stringToTest = nil;
if ([sortBy isEqualToString:@"FirstName"])
{
stringToTest = contact.firstName;
}
else if ([sortBy isEqualToString:@"LastName"])
{
stringToTest = contact.lastName;
}
else if ([sortBy isEqualToString:@"Company"])
{
stringToTest = contact.companyName;
}
stringToTest = [stringToTest stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([stringToTest length])
{
//Do the code with stringToTest
}
这是为了减少代码重复,也使用if / else