views:

248

answers:

7

Hey!

How can you compare against multiple possibilities in one argument?

Example:

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

if ((string == "hello") || (string == "dolly))

Would save me a lot of code if you could write that like this:

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

if (string == ("hello" || "dolly"))
+10  A: 

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 */
}
Jens Gustedt
+2  A: 

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.

paxdiablo
+1 for daily wtf :)
Richard J. Ross III
+7  A: 

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] )
kovpas
+3  A: 

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"])
John Calsbeek
+2  A: 

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

Fernando
A: 

If your integers are nonzero and small enough to fit in unsigned char or wchar_t, a convenient way to do this is something like:

if (strchr("\2\5", integer)) ...

or:

if (wcschr(L"\2\5", integer)) ...

Keep in mind those are octal values, not decimal. You could use hex (\x) if you prefer.

For strings, the way to make it efficient is to use a regular expression, or write your own DFA to accept the set of strings you want to test for.

R..
A: 

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.

Vovanium