【问题标题】:In Objective-C Check an array of Boolean Values and see if at least ONE is YES在 Objective-C 检查一个布尔值数组,看看是否至少 ONE 是 YES
【发布时间】:2013-09-04 16:40:55
【问题描述】:

我有一个可变的布尔值数组,我想检查是否有任何值是 YES。

目前我在这个数组旁边创建另一个数组,它总是像这样的 ALL False;

 [MyArray addObject:[NSNumber numberWithBool:switchInput]];
 [MyAllNoArray addObject:[NSNumber numberWithBool:NO]];

用户做了一些操作,MyArray 中的一些对象可能会变成 YES,然后我用下面的来看看 ANY 是否为真。

if([MyArray isEqualToArray:MyAllNoArray])

我只是想知道是否有更好的方法(这种方法似乎很浪费)?

我考虑过一个计数器,每次其中一个对象发生变化时,计数器都会上升或下降(取决于更改为 YES 或 NO),如果计数器为 0,则数组也是如此。但我只是想在我遗漏的 IF 语句中可能有更好的方法。

【问题讨论】:

  • 简单循环更快,概念上更简单。
  • 我喜欢柜台的想法。由于它是面向对象的,因此您可以封装该行为。通常我会说不要预先优化,但如果你知道数组可能很大,这似乎是一个很好的例子。

标签: ios objective-c arrays if-statement compare


【解决方案1】:

我认为更简单的解决方案是:

NSArray *bools = @[@(NO),@(NO), @(YES)];
    if ([bools containsObject:@(YES)]) {
        // do your magic here
    }

如果您只需要检查是否存在,那么循环和块将是一种矫枉过正。

【讨论】:

  • 不错! - 只有两点:1)containsObject: 很可能在内部使用循环,所以这个方法应该和显式循环一样快。 2)您可以写@YES(NSNumber 文字)而不是@(YES)(盒装表达式)。结果是一样的。
  • 我认为无论使用哪种方法,都会发生某种内部/外部循环。我勾选了这个,因为它是第一个有这个答案的,这个答案读起来非常好(很容易看)。
  • @MartinR 是的,这很好用,不确定我是否理解 @(YES),这是 [NSNumber numberWithBool:YES] 的现代 C++ 吗?
  • @RecycledSteel:这是一个(现代)Objective-C“盒装表达式”。见clang.llvm.org/docs/ObjectiveCLiterals.html
  • 这很棒。 Objective C 相对较新,语言看起来很冗长,非常感谢我可以让它不那么冗长!
【解决方案2】:
NSArray *myArray;

__block bool hasTrue = NO;
[myArray enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
    if (num.boolValue) {
        hasTrue = YES;
        *stop = YES;
    }
}];

if (hasTrue)
    NSLog(@"there is a true value in myArray.");
else
    NSLog(@"there is not true value in myArray.");

或者把它变成一个方法:

- (BOOL)doesMyArrayHaveTrue {
    NSArray *myArray;

    __block bool hasTrue = NO;
    [myArray enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
        if (num.boolValue) {
            hasTrue = YES;
            *stop = YES;
        }
    }];

    return hasTrue;
}

或者...我还没有尝试过,但我认为它应该可以工作:

NSNumber * max = [myArray valueForKeyPath:@"@max.self"];
if (max.boolValue)
    NSLog(@"there is a true values.");
else
    NSLog(@"there is not a true value.");

【讨论】:

  • 我喜欢最后一个(因为它是“盒子外”),我会试试看。
  • 最后一个使用键值编码的解决方案很简洁并且确实有效,但会扫描整个数组。
【解决方案3】:

最简单的方法是使用containsObject:@(YES)

说明

如果你查看它说的 NSArray 文档

包含对象: 返回一个布尔值,指示给定对象是否存在于数组中。

  • (BOOL)containsObject:(id)anObject

讨论

此方法通过向数组的每个对象发送 isEqual: 消息(并将 anObject 作为参数传递给每个 isEqual: 消息)来确定数组中是否存在 anObject。

所以containsObject:@(YES) 应该可以解决问题

【讨论】:

    【解决方案4】:

    与随机答案几乎相同,但没有块。

    bool allFalse = true;
    for(NSNumber *number in MyArray)
    {
        if([number boolValue])
        {
            allFalse = false;
            break;
        }
    }
    
    if(!allFalse)
    {
        ...
    }
    

    【讨论】:

    • 真的,我的快速枚举比 isEqualToArray 快吗?我想净总数是(在我弄乱了第二个数组之后)。
    • @RecycledSteel -- 你认为在 isEqualToArray 中必须发生什么?有一种神话般的信念,即使用“高级”函数比使用简单循环更快,等等。这偶尔是真的,但也经常不是。
    【解决方案5】:
    NSNumber* yesBool = [NSNumber numberWithBool:YES];
    BOOL foundYes = NO;
    for (NSNumber* num in MyArray) {
        if ([num isEqualToNumber:yesBool) {
            foundYes = YES;
            break;
        }
    }
    

    对于没有某种“分数”的测试,你不能做得更好 (*),尽管如果你选择“保持分数”,你的计数器方案无疑会更好。

    (*) 使用isEqualToNumber 是否比简单地测试boolValue 效率更高或更低是有争议的。

    【讨论】:

      【解决方案6】:

      这里有很多很好的答案,@Arcanfel 和@rr1g0 的简单使用containsObject: 的建议非常优雅和简单。

      尽管回答了该主题的许多受人尊敬的同事都遗漏了一个重要选项 - 基于谓词的解决方案。为了完整起见,这里是这样:

      NSArray *data = @[@(NO), @(YES), @(NO)];
      
      NSPredicate *hasYesPred = [NSPredicate predicateWithFormat: @"SUBQUERY(SELF, $s, $s == %@).@count > 0", @(YES)];
      
      BOOL hasYes = [hasYesPred evaluateWithObject: data];
      

      这里的想法是子查询构造一个等于@(YES)的对象数组,然后我们对其进行计数,如果它是正数,我们就知道其中至少有一个真正的布尔值大批。

      这种方法显然可以扩展到其他类型的数字——例如,确定一个数组中是否至少有一个负数。

      【讨论】:

      • 我同意了解所有选项并感谢您填补空白。我想我会选择 containsObject 选项,因为它比任何其他选项都好。
      猜你喜欢
      • 2021-11-14
      • 1970-01-01
      • 2017-10-31
      • 2011-03-05
      • 1970-01-01
      • 1970-01-01
      • 2015-09-22
      • 1970-01-01
      • 2012-10-27
      相关资源
      最近更新 更多