简体   繁体   English

检查NSMutableArray是否包含int

[英]Check if NSMutableArray contains an int

I am making an app which asks the user a series of questions. 我正在制作一个向用户询问一系列问题的应用程序。 The question asked depends on the random int produced. 问的问题取决于产生的随机int When an int is used, I want to add it to an NSMutableArray , and then check if the array contains a number the next time a random number is chosen. 当使用int ,我想将其添加到NSMutableArray ,然后在下次选择随机数时检查数组是否包含数字。 I am currently using the following code to do this: 我目前正在使用以下代码执行此操作:

- (void) selectQuestionNumber {
textNum = lowerBounds + arc4random() % (upperBounds - lowerBounds);

if ([previousQuestions containsObject:[NSNumber numberWithInt:textNum]]) {
    [self selectQuestionNumber];
    NSLog(@"The same question number appeared!");
} else {
    questionLabel.text = [self nextQuestion];
    [self questionTitleChange];

    NSLog(@"New question made");
}
[previousQuestions addObject:[NSNumber numberWithInt:textNum]];
}  

However, the code NSLog(@"The same question number appeared!"); 但是,代码NSLog(@"The same question number appeared!"); is never shown in the console, even when the same question will appear twice. 即使相同的问题将出现两次,也不会在控制台中显示。

My code is obviously non-functional, so what code can I use to check if an NSMutable array contains an int ? 我的代码显然无法正常工作,因此我可以使用什么代码检查NSMutable数组是否包含int

Your problem is likely something other than detecting membership of NSNumbers in an NSArray. 您的问题可能与检测NSArray中的NSNumbers成员身份不同。 It can take a large number of tries for a set of random numbers to repeat. 重复一组随机数可能需要大量尝试。 It is theoretically possible for it to not repeat until every possible value has been generated once. 从理论上讲,直到每个可能的值都生成一次才重复。 For a large range of legal values it can take quite a while. 对于各种各样的法律价值,可能要花相当长的时间。

I suggest logging the values that you add to the array on each pass, and the new value. 我建议记录每次通过时添加到数组的值以及新值。

Your code above always adds the new value to the array even it if matched, so your array is going to grow with duplicates. 上面的代码即使匹配也总是将新值添加到数组中,因此您的数组将随着重复项而增长。 You would be better off only adding the new number to the array if it did not match. 如果新数字不匹配,最好只将新数字添加到数组中。 you would probably also be better off using an NSMutableSet instead of an array. 您也可能最好使用NSMutableSet而不是数组。 NSSets contain at most one instance of an object, and their containsObject method is faster than that of NSArray. NSSet最多包含一个对象的一个​​实例,它们的containsObject方法比NSArray更快。

Original solution (works with Array and Set): 原始解决方案(适用于数组和集合):

-(void)selectQuestionNumber
 {
   textNum = lowerBounds + arc4random() % (upperBounds - lowerBounds);

    NSPredicate *predicate =  [NSPredicate predicateWithFormat:@"intValue=%i",textNum];
    NSArray *filteredArray = [previousQuestions filteredArrayUsingPredicate:predicate];

    if ([filteredArray count]) {
        [self selectQuestionNumber];
        NSLog(@"The same question number appeared!");
    } else {
        questionLabel.text = [self nextQuestion];
        [self questionTitleChange];

        NSLog(@"New question made");
    }
    [previousQuestions addObject:[NSNumber numberWithInt:textNum]];
}

Best solution, and better performance, especialy with mutableSet ( According to Duncan C). 最佳解决方案和更好的性能,尤其是使用mutableSet(根据Duncan C)。

 -(void)selectQuestionNumber
{

textNum = lowerBounds + arc4random() % (upperBounds - lowerBounds);

if ([previousQuestions containsObject:[NSNumber numberWithInteger:textNum]]) {
    [self selectQuestionNumber];
    NSLog(@"The same question number appeared!");
} else {
    questionLabel.text = [self nextQuestion];
    [self questionTitleChange];

    NSLog(@"New question made");
    // And add the new number to mutableSet of mutableArray.
    [previousQuestions addObject:[NSNumber numberWithInteger:textNum]];
}

}

Instead of using NSArray, you can use NSMutableIndexSet. 可以使用NSMutableIndexSet代替使用NSArray。 This is the same as NSSet, with just NSUIntegers instead of objects. 这与NSSet相同,只是NSUIntegers而不是对象。 Very useful. 很有用。

//during init
NSMutableIndexSet *tSet = [[NSMutableIndexSet alloc] init];
//...
//later in the code, in whatever loop you have on new values
NSUInteger newInt = lowerBounds + arc4random() % (upperBounds - lowerBounds);
if ([tSet containsIndex:newInt]){
    //value already exists in the set
}
else {
    //value does not exist, add it
    [tSet addIndex:newInt];
}
NSMutableSet *myNumbers = [NSMutableSet Set]; // or NSMutableArray..


NSNumber *aNumber = [NSNumber numberWithInt:getRandomInt() ]; //let us say it returns 1.

[myNumbers addObject:aNumber];



    -(BOOL)succesfullyAddNewUniqueRandomMember{

        NSInteger randInt = getRandomInt(); //let us say it returns 1 again..

        NSNumber *aSubsequentNumber = [NSNumber numberWithInt:randInt;

 for (NSNumber *previousEntry in myNumbers){


  if ([previousEntry isEqual:aSubsequentNumber]) return NO;

  }
[myNumbers addObject:aSubsequentNumber];
 return YES;

}

^ are these objects equal (aNumber, aSubsequentNumber) ? ^这些对象是否相等(aNumber,aSubsequentNumber)? YES

^ are they the same object ? ^他们是同一个对象吗? NO, two different NSNumbers made with equal integer.. 不,两个不同的NSNumber用相等的整数组成。

NSSet will also happily add both, because they are not the same object. NSSet也将很高兴将两者都添加,因为它们不是同一对象。

therefore you need to loop through and compare directly to each previous member, the (already contains object) filter of NSSet will not do the trick. 因此,您需要遍历并直接与每个先前的成员进行比较,NSSet的(已经包含对象)过滤器将无法解决问题。

by wrapping this in a -(BOOL) type method we can repeat it with a 通过将其包装在-(BOOL)类型的方法中,我们可以使用

while(![self succesfullyAddNewUniqueRandomMember])

In other words, in your code 换句话说,在您的代码中

if ([previousQuestions containsObject:[NSNumber numberWithInt:textNum]])

always returns NO because it is comparing NSNumber objects, not their integerValue. 总是返回NO,因为它在比较NSNumber对象,而不是它们的integerValue。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM