【问题标题】:Objective-C ugly code?Objective-C 丑陋的代码?
【发布时间】:2011-07-06 10:17:56
【问题描述】:

我有一些 Objective-C 代码可以为我完成这项工作。但它丑陋(低效)吗?使用 for-each 循环可以更好地执行吗?

请看这段代码:

for (int i = 0; i < [careerIds count]; i++) {

    NSString *titleString = [[titles objectAtIndex:i] stringValue];
    if ([titleString isEqualToString:@""] || [titleString rangeOfString:@"Intresseanmälan"].location != NSNotFound) {
        // Don't add the id
    } else {
        [ids addObject:[[careerIds objectAtIndex:i] stringValue]];
    }

}

【问题讨论】:

  • 可能不会。这有点难看,但我认为在这种情况下担心效率可能是错误的。
  • 如果您担心速度,请参阅this answer @Deepak 实际上对各种选项进行计时,并发现不使用快速迭代比使用快速迭代更快,如果这意味着您还必须-indexOfObject。或者至少在案例中经过测试。

标签: objective-c performance for-loop


【解决方案1】:

我不认为你的代码特别难看——像你所做的那样使用索引 for 循环没有任何问题。我唯一可能改变的就是颠倒if 语句的含义,这样你就可以避免空的// Don't add the id 行。这是一种方法:

for (int i = 0; i < [careerIds count]; i++) {

    NSString *titleString = [[titles objectAtIndex:i] stringValue];

    if (([titleString length] > 0) && 
        ([titleString rangeOfString:@"Intresseanmälan"].location == NSNotFound))
    {
        [ids addObject:[[careerIds objectAtIndex:i] stringValue]];
    }

}

要解决您问题的核心,不,我不认为可以使用for 循环的快速枚举版本同时迭代两个单独容器的内容。您可以将它与一个一起使用,但正如我在评论中指出的那样,您必须使用 -indexOfObject: 来恢复当前对象的索引,以便您可以使用 -objectAtIndex: 从另一个数组中获取相应的项目。

【讨论】:

  • 您应该能够毫无问题地删除([titleString length] &gt; 0),或者可能只是删除titleString,以检查它是否不是nil,但我怀疑这是否是必要的。
  • @Deepak titleString 永远不应该是nil,但它可能是@"",在这种情况下rangeOfString 将返回NSNotFound,并且对象添加将被错误地执行。
  • @walkytalky 啊!我明白你在说什么。我没想到会是 nil,但是是的,我对 @"" 部分的看法是错误的。
  • @Deepak,我本可以说![titleString isEqualToString:@""],但是(对我来说)很容易错过!而且我认为使用 length > 0 可以更好地传达“非空”。你是对的,在上面的代码中 titleString 永远不应该是 nil,但是在测试字符串可能是 nil 的情况下,[titleString length] &gt; 0 会做预期的事情(评估为 NO)。
  • 为了让它不那么难看(将来更容易阅读),您可以添加一个名为 BOOL 的好名称,例如 BOOL isTitleValid = ([titleString length] &gt; 0) &amp;&amp; ([titleString rangeOfString:@"Intresseanmälan"].location == NSNotFound);,然后在 if 语句中使用 isTitleValid 变量。这只是意味着您不必反复检查即可弄清楚您最初检查的是什么。
【解决方案2】:

使用 for-each 循环可以更好地执行吗?

是的。

for (id title in careerIds) {

    NSString *titleString = [title stringValue];
    if ([titleString isEqualToString:@""] || [titleString rangeOfString:@"Intresseanmälan"].location != NSNotFound) {
        // Don't add the id
    } else {
        [ids addObject:titleString];
    }
}

或者如果你想成为真正的闪光:

for (NSString* titleString in [careerIds valueForKey: @"stringValue"]) {

    if ([titleString isEqualToString:@""] || [titleString rangeOfString:@"Intresseanmälan"].location != NSNotFound) {
        // Don't add the id
    } else {
        [ids addObject:titleString];
    }
}

没有。 :-)

【讨论】:

  • 检查问题:正在添加的对象与正在测试的对象来自不同的来源。所以答案可能真的是“不”。
  • 这些似乎都不像 OP 的代码那样。在原始代码中,titleString 来自 titles 数组,它不会出现在您的代码中的任何位置。如果careerIdstitles 是并行数组,那么您必须先将它们连接到一个数组中,或者使用-indexOfObject:,或者使用原始代码中的传统索引for 循环。
【解决方案3】:

假设 careerIds 是一个 NSArray 或 NSMutableArray 并且您要向其中添加 NSString 对象,您可以这样做:

for (NSString *titleString in careerIds) {

    if ([titleString isEqualToString:@""] || [titleString rangeOfString:@"Intresseanmälan"].location != NSNotFound) {
        // Don't add the id
    } else {
        [ids addObject: titleString];
    }
}

[ids addObject:[[careerIds objectAtIndex:i] stringValue]];

【讨论】:

  • 查看我对@JeremyP 回答的评论。此代码不会复制原始功能。
  • 哦,您在使用i 时没有声明或定义它。无论谁赞成这个都需要严厉的谈话。
  • 哎呀,我想我应该仔细检查一下。我只是在看 for 循环。我没有对里面的代码做任何事情。谢谢你抓住那个。 :)
猜你喜欢
  • 2011-02-03
  • 1970-01-01
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
  • 2022-11-26
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多