根据联系人姓名获取 sectionIndex 标题 [英] Get sectionIndex titles based on contact name

查看:58
本文介绍了根据联系人姓名获取 sectionIndex 标题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序中,我有一个包含 5 万多个联系人的数据库.要在列表视图中显示它们,我需要计算索引部分标题以将它们显示在右侧.

In my app I have a db with 50k+ contacts. To display them on list view, I need to calculate the index section titles to display them on the right side.

但是我的逻辑需要大约 3-6 秒的时间来准备数据源.

However my logic is taking time around 3-6 seconds to prepare the datasource.

-(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:)];
}

我想知道我是否可以做些什么来改善这一点.

I'm wondering if there is anything I could do to improve this.

 NSString *firName= [contact.firstName stringByReplacingOccurrencesOfString:@" " withString:@""];
 NSString *regex = @"^[A-Za-z]+";
  NSPredicate *test = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
  BOOL result = [test evaluateWithObject:firName];

我这样做是为了检查字符串是否包含特殊字符或无效字符.

I'm doing this to check if string contain special chars or invalid chars.

得到数组后,我对它进行排序并返回数组.输出将是:

After I get the array, I sort it and return the array. The output would be:

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;
}

推荐答案

我是这样做的:

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: 比 Regex/Predicate 快.
• 因为您只对大写感兴趣,所以我在进行测试之前而不是之后对其进行了翻译,这也可以加快您案例中的谓词.

What are the differences?
• I used of a NSSet instead of a NSDictionary for the unicity of first letters. I find useless to use a NSDictionary with a unused value and just for the unicity of the keys.
• I used stringByTrimmingCharactersInSet: instead of stringByReplacingOccurrencesOfString:withString:. In theory, the code of stringByTrimmingCharactersInSet: should stop at the first char which isn't of the set, and not continue until the end of the string like stringByReplacingOccurrencesOfString:withString:.
• I guess that characterIsMember: is faster than a Regex/Predicate.
• Since you are only interested in uppercase, I translated it before doing the test, and not after, that could also speed the predicate in your case.

此外,代码中的小错误:

Also, small errors on your code:

if (contact.firstName.length>0 && result) 

[nameDic setObject:@"firstletter" forKey:[[contact.firstName substringToIndex:1]uppercaseString]]; 

应该使用 firName 而不是 contact.firstName.

should use firName instead of contact.firstName.

此测试样本上,我的解决方案似乎比您的解决方案 (x10) 快.我在 OS X 应用程序(不是 iOS)上进行了快速测试.我没有做很多测试,但可能值得一试.

On this test sample, my solution seems to be faster than yours (x10). I tested quickly on a OS X App (not iOS). I didn't do a lot of testings, but it may worth a try.

我不知道是不是为了这个问题,但是,你可以做的代码优化:

I don't know if it just for the question, but, the code optimization you could do:

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

It's for less code duplication and also use of if/else

这篇关于根据联系人姓名获取 sectionIndex 标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆