大条件将元素放入段数组中,更好的方法? - 目标-C

时间:2012-01-26 04:18:02

标签: objective-c cocoa-touch uitableview conditional

我有这段代码用于将数组中的元素放入UITableView中的相应部分,具体取决于它们的起始字母:

//For each product in the appDelgates products
for (Product *product in appDelegate.m_Products){
    if ([product.category isEqualToString:productType]){

        //firstLetter is equal to the first letter of the products name
        NSString * l_FirstLetter = [product.name substringToIndex:1];
        //convert firstString to uppercase
        l_FirstLetter = [l_FirstLetter uppercaseString];

        //Check what letter firstString is equal to in the alphabet
        //Place in appropriate section
        //If none, place in "Other" category
        if ([l_FirstLetter isEqualToString:@"A"]) {
            [[m_AlphabetDictionary objectAtIndex:0] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"B"]) {
            [[m_AlphabetDictionary objectAtIndex:1] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"C"]) {
            [[m_AlphabetDictionary objectAtIndex:2] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"D"]) {
            [[m_AlphabetDictionary objectAtIndex:3] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"E"]) {
            [[m_AlphabetDictionary objectAtIndex:4] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"F"]) {
            [[m_AlphabetDictionary objectAtIndex:5] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"G"]) {
            [[m_AlphabetDictionary objectAtIndex:6] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"H"]) {
            [[m_AlphabetDictionary objectAtIndex:7] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"I"]) {
            [[m_AlphabetDictionary objectAtIndex:8] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"J"]) {
            [[m_AlphabetDictionary objectAtIndex:9] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"K"]) {
            [[m_AlphabetDictionary objectAtIndex:10] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"L"]) {
            [[m_AlphabetDictionary objectAtIndex:11] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"M"]) {
            [[m_AlphabetDictionary objectAtIndex:12] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"N"]) {
            [[m_AlphabetDictionary objectAtIndex:13] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"O"]) {
            [[m_AlphabetDictionary objectAtIndex:14] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"P"]) {
            [[m_AlphabetDictionary objectAtIndex:15] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"Q"]) {
            [[m_AlphabetDictionary objectAtIndex:16] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"R"]) {
            [[m_AlphabetDictionary objectAtIndex:17] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"S"]) {
            [[m_AlphabetDictionary objectAtIndex:18] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"T"]) {
            [[m_AlphabetDictionary objectAtIndex:19] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"U"]) {
            [[m_AlphabetDictionary objectAtIndex:20] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"V"]) {
            [[m_AlphabetDictionary objectAtIndex:21] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"W"]) {
            [[m_AlphabetDictionary objectAtIndex:22] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"X"]) {
            [[m_AlphabetDictionary objectAtIndex:23] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"Y"]) {
            [[m_AlphabetDictionary objectAtIndex:24] addObject:product];
        }
        else if ([l_FirstLetter isEqualToString:@"Z"]) {
            [[m_AlphabetDictionary objectAtIndex:25] addObject:product];
        }
        else {
            [[m_AlphabetDictionary objectAtIndex:26] addObject:product];
        }

    }
}

有更好的方法吗?

谢谢,

杰克

5 个答案:

答案 0 :(得分:3)

将char转换为int减去“A”

的char的int

并使用[[m_AlphabetDictionary objectAtIndex:myInt] addObject:product];

并确保,您只使用字母。如果你想支持小写和大写字母,你必须从小写字母中减去'a'的字符。

如果您将来需要支持区域设置和变音符号,那么有更复杂的方法,但这适用于OP中定义的a ... z和A ... Z集:

首先,罗嗦版本记录了它的工作原理:

static inline NSUInteger InsertionIndexForProductNamed(NSString * product) {
  assert(0 < product.length && "invalid argument");

  const int A = 'A';
  const int Z = 'Z';
  const int a = 'a';
  const int z = 'z';

  const unichar first = [product characterAtIndex:0];
  const bool isLowercaseAZ = a <= first && z >= first;
  const int uppercase = isLowercaseAZ ? (first + A - a) : first;
  const bool isUppercaseAZ = A <= uppercase && Z >= uppercase;

  if (isUppercaseAZ) {
    const int result = uppercase - A;
    return (NSUInteger)result;
  }
  else {
    /* not A-Z. place in 'other' */
    return 26;
  }
}

现在是简短的版本,它更像你在野外看到的那些:

static inline NSUInteger InsertionIndexForProductNamed(NSString* product) {
  assert(0 < product.length && "invalid argument");

  const unichar first = [product characterAtIndex:0];
  switch (first) {
    case 'A'...'Z' :
      return first - 'A';
    case 'a'...'z' :
      return first - 'a';
    default :
      return 26;
  }
}

使用中:

/* For each product in the appDelgates products */
for (Product * product in appDelegate.m_Products) {
  if ([product.category isEqualToString:productType]) {
    const NSUInteger idx = InsertionIndexForProductNamed(product.name);
    [[m_AlphabetDictionary objectAtIndex:idx] addObject:product];
  }
}

最后,简短的在线实施可以采用以下形式:

/* For each product in the appDelgates products */
for (Product * product in appDelegate.m_Products) {
  if ([product.category isEqualToString:productType]) {
    const NSUInteger insertionIndex;
    const unichar first = [product characterAtIndex:0];
    switch (first) {
      case 'A'...'Z' :
        insertionIndex = first - 'A';
        break;
      case 'a'...'z' :
        insertionIndex = first - 'a';
        break;
      default :
        insertionIndex = 26; // 26 is the index of the 'other' category
        break;
    }
    [[m_AlphabetDictionary objectAtIndex:insertionIndex] addObject:product];
  }
}

还请注意我的ObjC/Block-style answer

答案 1 :(得分:1)

与字符混淆让你得到奇怪的问题,你在[0,25]之外的标记处添加对象,这是一个很大的禁忌。通过明确声明您的词典,您可以确保避免使用它。

 bool added = NO;
 NSArray* theAlphabet = [NSArray arrayWithObjects:@"A",@"B",@"C" ... ,@"Z",nil];
 for(int i=0; i<26; i++){
     if ([l_FirstLetter isEqualToString:[theAlphabet objectAtIndex:i]]) {
        [[m_AlphabetDictionary objectAtIndex:i] addObject:product];
        added = YES;
     }
 }
 if(!added)
     [[m_AlphabetDictionary objectAtIndex:26] addObject:product];

added标志确保第一个字母不是字母的对象被添加到数组26中。

答案 2 :(得分:0)

详细说明vikingosegundo的答案:

for (Product *product in appDelegate.m_Products) {
    if ([product.category isEqualToString: productType]) {
        NSString* l_FirstLetter = [product.name substringToIndex: 1];
        l_FirstLetter = [l_FirstLetter uppercaseString];

        NSInteger key = l_FirstLetter - 'A';
        [[m_AlphabetDictionary objectAtIndex: key] addObject: product];
    }
}

这是因为Objective-C允许您从NSString中减去char('A')。您可能必须先将l_FirstLetter转换为char。

答案 3 :(得分:0)

C提供了测试不同类别字符的标准函数,因此我们可以将代码缩短为:

//For each product in the appDelgates products
for (Product *product in appDelegate.m_Products)
{
   if ([product.category isEqualToString:productType])
   {
       //firstLetter is equal to the first letter of the products name in uppercase
       int l_FirstLetter = toupper([product.name characterAtIndex:1]);

       //Place in appropriate section, if none, place in "Other" category
       unsigned index = isupper(l_FirstLetter) ? (l_FirstLetter - 'A') : 26;
       [[m_AlphabetDictionary objectAtIndex:index] addObject:product];
   }
}

答案 4 :(得分:0)

在我的另一个C-style answer旁边(再次感谢@Justin),我想假设另一个答案。

这次我只使用objective-c语法和块。

创建一个单词数组:

NSString *text = @"Lorem ipsum dolor sit amet,..."; // Lorem ipsum with non-letter words
NSArray *words = [[[text stringByReplacingOccurrencesOfString:@"." withString:@""] 
                         stringByReplacingOccurrencesOfString:@"," withString:@""] 
                            componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

创建并填写字典:

NSMutableDictionary *wordDict = [NSMutableDictionary dictionary];
[words performBlock:^(id element) {
    NSString *firstLetter = [[element substringToIndex:1] uppercaseString];
    if ([firstLetter isGreaterThanOrEqualTo:@"A"] && [firstLetter isLessThanOrEqualTo:@"Z"]){
        if (![[wordDict allKeys] containsObject:firstLetter]) {
            NSMutableArray *array = [NSMutableArray array];
            wordDict[firstLetter] = array;
        }

        [wordDict[firstLetter] addObject:element];
    } else {
        if (![[wordDict allKeys] containsObject:@"other"]) {
            NSMutableArray *array = [NSMutableArray array];
            wordDict[@"other"] = array;
        }
        [wordDict[@"other"] addObject:element];
    }
}];

NSLog(@"%@",wordDict);

请注意,此代码在NSArray performBlock:上使用类别方法。此方法只是将块应用于数组中的每个元素。 It can be found at github

-(void)performBlock:(void (^)(id))block
{
    for(id element in self) {
        block(element);
    }
}

输出

{
    A =     (
        amet,
        aliquyam,
        At,
        accusam,
        amet,
        amet,
        aliquyam,
        At,
        accusam,
        amet,
        amet,
        aliquyam,
        At,
        accusam,
        amet
    );
    C =     (
        consetetur,
        clita,
        consetetur,
        clita,
        consetetur,
        clita
    );
    //…
    L =     (
        Lorem,
        labore,
        Lorem,
        Lorem,
        labore,
        Lorem,
        Lorem,
        labore,
        Lorem
    );
    //…
    T =     (
        tempor,
        takimata,
        tempor,
        takimata,
        tempor,
        takimata
    );
    U =     (
        ut,
        ut,
        ut
    );
    V =     (
        voluptua,
        vero,
        voluptua,
        vero,
        voluptua,
        vero
    );
    other =     (
        "%$",
        "!",
        "9)7/",
        1234,
        56hfr
    );
}