emmalyx
emmalyx

Reputation: 2356

Instead of switch-case, select string more efficiently

First off, I'm sorry for the question title.

Now, the question: I'm writing an iPhone app that reads compass values and displays the name of direction the device is facing. As of writing, I do it like this:

switch (trueHeadingRounded) {
    case 23 ... 68:
        cardinalDirection = @"northeast";
        break;
    case 69 ... 114:
        cardinalDirection = @"east";
        break;
    //ad infinitum

How can I shorten this part? There has to be a better way.

Upvotes: 2

Views: 87

Answers (5)

Hot Licks
Hot Licks

Reputation: 47739

NSString* cardinalDirection = @[@"north", @"northeast", @"east", @"southeast", @"south", @"southwest", @"west", @"northwest", @"north"][(trueHeadingRounded + 23) / 45];

It might be I'm off on the 23 constant or some such -- I haven't double-checked my calcs. (But I kinda agree with Zaph.)

(And, of course, if you really did this it would probably be wise to make the array a relative constant -- inited class property or some such -- for efficiency's sake.)

Upvotes: 1

vikingosegundo
vikingosegundo

Reputation: 52237

You could increase readability by using named constants and not magic numbers

typedef NS_ENUM(NSInteger, Heading) {
    HeadingNorth = -1,
    HeadingNorthEast,
    HeadingEast,
    HeadingSouthEast,
    HeadingSouth,
    HeadingSouthWest,
    HeadingWest,
    HeadingNorthWest
};

You could than alter your switch statement

Heading heading = floor((trueHeadingRounded - 23) / 45);

NSString *cardinalDirection;

switch (heading) {
    case HeadingNorth:      cardinalDirection = @"north";       break;
    case HeadingNorthEast:  cardinalDirection = @"northeast";   break;
    case HeadingEast:       cardinalDirection = @"east";        break;
    case HeadingSouthEast:  cardinalDirection = @"southeast";   break;
    case HeadingSouth:      cardinalDirection = @"south";       break;
    case HeadingSouthWest:  cardinalDirection = @"southwest";   break;
    case HeadingWest:       cardinalDirection = @"west";        break;
    case HeadingNorthWest:  cardinalDirection = @"northwest";   break;
}
NSLog(@"%@", cardinalDirection);

Upvotes: 1

Bryan Polyak
Bryan Polyak

Reputation: 40

you can use something like:

cardinalDirection = ( trueHeadingRounded <= 22 ? @"north" :
                      trueHeadingRounded <= 68 ? @"northeast" :
                      treuHeadingRounded <= 114 ? @"east" :

etc.

However, I think I'd use the mapping array suggestion.

Upvotes: 0

Fabien Warniez
Fabien Warniez

Reputation: 2741

You could do the following:

  1. Create an arithmetic function that gives you a number based on the angle. That number would be between 0 and 7 (0 for northeast, 1 for east, and so on). Would look like (x - 23) / 45 or something like that.
  2. Then create a mapping array that gives you the name of the direction from a number. [0] => 'Northeast', [1] => 'East', etc.
  3. Lookup in the array the name to be returned. return mappingArray[indexFromAngle(x)]

Upvotes: 5

zaph
zaph

Reputation: 112855

Don't write code to shorten it, write code to make it more understandable. Clarity is everything.

If there is a concern about performance write for clarity, then if there is a performance problem profile to find exactly what and where and then fix that.

Upvotes: 3

Related Questions