根据联系人姓名获取 sectionIndex 标题
Posted
技术标签:
【中文标题】根据联系人姓名获取 sectionIndex 标题【英文标题】:Get sectionIndex titles based on contact name 【发布时间】:2017-08-14 13:38:20 【问题描述】:在我的应用程序中,我有一个拥有 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;
【问题讨论】:
我这样做了:pastebin.com/ixHsPSxh 在 OSX 模拟器上测试,似乎更快(x10,但没有做更多测试)。此外,代码中的小错误:if (contact.firstName.length>0 && result)
和 [nameDic setObject:@"firstletter" forKey:[[contact.firstName substringToIndex:1]uppercaseString]];
应使用 firName
而不是 contact.firstName
。
【参考方案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 应用程序(不是 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 的使用
【讨论】:
感谢您的努力! 出于好奇,在您说您的解决方案需要“3-6 秒”之前。现在?你有足够的进步吗? 现在是即时的。 200k + 联系人需要 2-3 秒。 太棒了!要添加的一个小优化可能是如果您有那么多联系,您可能会认为会有所有字母和其他,那么您可能想做if ([set count] == 27)break;
它可能会或不会紧固一点。以上是关于根据联系人姓名获取 sectionIndex 标题的主要内容,如果未能解决你的问题,请参考以下文章