Quicker if-statement: if `variable` is “value” or “value”

前端 未结 7 2106
感情败类
感情败类 2020-12-18 15:44

How can you compare against multiple possibilities in one argument?

Example:

if ((integer == 2) || (integer == 5))

if ((string == \"hello\") || (str         


        
相关标签:
7条回答
  • 2020-12-18 16:08

    Actually, you can check if NSSet contains some object. This won't work with int, as it's not an object, but will work with NSString.

    I believe it could be written like this:

    if ( [[NSSet setWithObjects:@"hello", @"dolly", nil] containsObject:string] )
    

    So, if you want to compare ints, you should wrap them with NSNumber.

    This won't save a lot of code if you are not comparing tens of objects, but this looks pretty similar to what you want to get :)

    UPDATE:

    Or another way (quite similar to the answer from John Calsbeek, but works for multiple arguments):

    @implementation NSObject (IsEqualMultiple)
    
    - (BOOL)isEqualToOneOfObjects:(id)firstObject, ... {
        id eachObject;
        va_list argumentList;
    
        if (firstObject) {
            if ( [self isEqual:firstObject] ) return YES;
    
            va_start(argumentList, firstObject);
    
            while (eachObject = va_arg(argumentList, id))
                if ( [self isEqual:eachObject] ) return YES;
            va_end(argumentList);
        }
    
        return NO;
    }
    
    @end
    

    Usage:

    if ( [string isEqualToOneOfObjects:@"hello", @"dolly", @"this", @"is", @"Louis", nil] )
    
    0 讨论(0)
  • 2020-12-18 16:11

    At first, you should remember that good compiler should optimize multiple comparisons if it can draw conclusions about them, for example if value is compared through set of literals. So there's no need to 'optimize' expressions like x==1 || x==3 || x==7 by hand.

    In C, works for integers in range 0..31 (or thich bits have your long, but you may use long long instead)

    if(((1UL<<val1)|(1UL<<val2)|(1UL<<val3)) & (1UL<<x)) ...
    

    This creates number having ones in bits corresponding to values should evaluate to true. It is convenient if you need to compare with variable list of small integers.

    You may also use sorted array of values and c standard function bsearch():

    int valuelist[] = { /* note it sorted */
        2, 5, 17, 33, 99, 103, 808
    }
    
    int valuelist_length = sizeof(valuelist)/sizeof(int);
    /* this works only for statically allocated non-external arrays, */
    /* you may need another method of evaluating number of items */
    
    int compar_int(const void *a, const void *b) {
        return ((const int *)b < (const int *)a) - ((const int *)a < (const int *)b);
    }
    ...
    
    if(bsearch(&x, valuelist, sizeof(int), valuelist_length, compar_int)) {
        /* bsearch returns pointer to found value or NULL if it is not found */
        /* so it will be evaluated as true if value exists in array */
    }
    

    But this is efficient only if you have really many numbers to compare.

    0 讨论(0)
  • 2020-12-18 16:14

    First of all string comparasion doesn't work that way in C, I know nothing about objective-c, thought.

    For the comparison against compile time integral constants, in C you have the switch statement:

    switch (integer) {
    case 2: ;
    case 5: ;
       /* do stuff here */
    }
    
    0 讨论(0)
  • 2020-12-18 16:15

    Create a variadic function or one that receives an array of strings for the comparison.

    0 讨论(0)
  • 2020-12-18 16:18

    This isn't part of the language. If you really want to avoid the typing, you could just create a function to do it, something along the lines of:

    int intIsIn (int needle, int *haystack, size_t sz);
    :
    if (intIsIn (integer, {2,5}, 2)) ...
    

    (and similar for other data types). I question the usefulness of this approach however because (1) it's only less typing for longer lists; and (2) you'll probably end up on "The Daily WTF" :-)

    My opinion would be to just suck it up, it's not really that much typing.

    0 讨论(0)
  • 2020-12-18 16:19

    If you wanted to do this with an object type, like say NSString, and you feel comfortable with categories, you could do add a category method:

    @implementation NSObject (IsEqualMultiple)
    
    - (BOOL)isEqualTo:(id)obj1 or:(id)obj2 
    {
        return [self isEqual:obj1] || [self isEqual:obj2];
    }
    
    @end
    

    Then you could use it like this:

    if ([string isEqualTo:@"hello" or:@"dolly"])
    
    0 讨论(0)
提交回复
热议问题