Sam Spencer
Sam Spencer

Reputation: 8609

More efficient way to write conditionals with lots of OR operators

How can I (more) efficiently write out an if / else conditional that uses the same variable and a huge amount of OR operators?

I've been banging my head on the desk trying to think of a way around writing out all of these OR operators with the same comparison. For loops won't do the trick, and I'm pretty certain that a do / while loop wouldn't do it either. A switch / case might solve this, but I don't think it could condense the code or make it any less tedious to write out.

The example below illustrates my dilemma. The API has a protocol method which is called for each section in the collection and needs a return value for the number of items in that section. Essentially, the protocol method below is a fancy for loop.

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    if (section == 0 || section == 31) return 7;
    else if (section == 1 || section == 26 || section == 27 || section == 28 || section == 29 || section == 30) return 6;
    else if (section == 2 || section == 3 || section == 4 || section == 5 || section == 6 || section == 7 || section == 8 || section == 9 || section == 10 || section == 11 || section == 12 || section == 13 || section == 14 || section == 15) return 2;
    else if (section == 16 || section == 17 || section == 18 || section == 19 || section == 20 || section == 21 || section == 22 || section == 23 || section == 24 || section == 25) return 4;
    else return 7;
}

As you can see in the extremely tedious if / else conditional I've written, it checks for every single section. I feel like I'm missing something - that Objective-C provides a nifty way around this kind of tedious and inefficient conditional writing / checking?

Upvotes: 0

Views: 87

Answers (3)

user1196549
user1196549

Reputation:

A clean way is to use a switch statement. These are usually implemented with a branching array, so are quite efficient.

switch (section)
{
case 0:
case 31:
    return 7;
...
}

And the most efficient of all (branchless) is a lookup-table:

const int nums[]= { 7, 6, 2, 2, 2... };

return nums[section];

Upvotes: 3

Vincent Guerci
Vincent Guerci

Reputation: 14419

A generic approach to this is to use NSArray / NSDictionary to build indexes, something like:

NSArray *sections = @[@3, @5, @27, ...];
if ([sections containsObject:@3]) ...

or

NSDictionary *sections = @{ @5: @27, @7: @23, ... };
int value = [sections[@(section)] intValue]

Upvotes: 1

Hot Licks
Hot Licks

Reputation: 47699

switch is probably the right answer, but you can also use shift/mask, something like:

int sectionBit = 0x00000001 << section;
if (sectionBit & 0x80000001) return 7;
if (sectionBit & 0x7c000002) return 6;
etc

The disadvantage of this approach is that it's tedious and error-prone to define the bit constants, but one can sometimes develop the constants by using enums, etc (at the expense of long declaration strings).

Upvotes: 1

Related Questions