2012-03-30 4 views
1

Ich habe viele Bereiche auf einen Wert wie 0-300 = 10, 300-600 = 20, 600-900 = 30 ... 2500000-2700000 = 7000 .... Also könnte ich eine wirklich große machen switch-statement/if-block, aber ich frage mich, ob es einen eleganteren Ansatz gibt, dieses kleine Problem zu lösen.Gibt es elegantere Lösungen für eine große Switch-Anweisung?

Ok hier ist eine kleine Teilmenge der Tabelle mit realen Daten:

0-300 : 25 
301-600. : 45 
601-900 : 65 
901-1200. : 85 
1201-1500: 105 

1501-2000 : 133 
2001-2500 : 161 
2501-3000: 189 
3001-3500:217 
3501-4000:245 

4001-4500:273 
4501-5000:301 
5001-6000:338 
+0

O <= 300 = 10, 300 <600 = 20 so 300 = 10 – Pfitz

+0

Also jeden 300 erhöhen Sie das Ergebnis um 10? Welches Ergebnis erwarten Sie für 1150? Und bist du dir sicher über das Ergebnis '2500000 => 7000'? Das passt nicht zum Muster. – sch

Antwort

5

Das häufigste Muster für eine switch-Anweisung loszuwerden ist ein Wörterbuch zu verwenden. In Ihrem Fall, da Sie Bereiche zuordnen, verwenden Sie stattdessen einen NSArray Bereich Cutoffs. Dies ist, wie es aussehen würde, wenn Sie mit ints zu tun hat:

NSArray *rangeCutoffs = [NSArray arrayWithObjects:[NSNumber numberWithInt:300],[NSNumberWithInt:600],...,nil]; 
NSArray *values = [NSArray arrayWithObjects:[NSNumber numberWithInt:10], [NSNumber numberWithInt:20],...,nil]; 

int mappedInt; 
for (int index=0; index <= [rangeCutoffs count]; index++) { 
    if (intToMap < [[rangeCutoffs objectAtIndex:index] intValue]) { 
     mappedInt = [[values objectAtIndex:index] intValue]; 
    } 
} 
if (mappedInt == 0) { 
    mappedInt = [[values lastObject] intValue]; 
} 

In der Praxis würden Sie wollen rangeCutoffs und values von einem plist laden, anstatt sie zu hartzucodieren.

1

Sie könnten eine Tabelle verwenden. z.B.

struct Lookup 
{ 
    int min; 
    int max; 
    int value; 
}; 

struct Lookup table[] = 
{ 
    {  0,  300, 10 }, 
    {  301,  600, 20 }, 
    {  601,  900, 30 }, 
    // other ranges 
    { 2500000, 2700000, 7000 }, 
    { -1, -1, -1 } // marks the end of the table 
}; 

Und dann einfach durchlaufen den richtigen Bereich

int result = -1; 
for (int i = 0 ; table[i].min != -1 && result == -1 ; ++i) 
{ 
    if (table[i].min <= value && value <= table[i].max) 
    { 
     result = table[i].value; 
    } 
} 

zu finden, wenn es ein wirklich großer Tisch ist, können Sie stattdessen eine binäre Suche verwenden können.

+0

Die Werte, die erwartet werden, gehen von 10 bis 7000 (und vielleicht mehr). Es ist nicht sinnvoll, 700 Zeilen Code zu schreiben, um 'table' zu ​​definieren. – sch

+0

@sch: Wie sonst wird er alle möglichen Fälle bekommen? Sie müssen irgendwo eingegeben werden. – JeremyP

+0

Die Werte, die ich verwendete, sind nur Beispiele. Es werden einige Werte sein, aber ich muss sie trotzdem über Code/Plist fest codieren. – Pfitz

0

Man könnte so etwas wie dieses (C Beispiel) tun:

#include <stdio.h> 
#include <stdlib.h> 

typedef int range_type; 
typedef int value_type; 

typedef struct { 
    range_type min; 
    range_type max; 
    value_type value; 
} range_t; 

const range_t *find_range(const range_t *ranges, size_t rangesSize, 
    value_type valueToFind) 
{ 
    for (size_t i = 0; i < rangesSize; ++i) { 
     if (ranges[i].min <= valueToFind && valueToFind <= ranges[i].max) 
      return &ranges[i]; 
    } 
    return NULL; 
} 

int main() { 
    const range_t ranges[] = { 
     { 0, 300, 10 }, 
     { 301, 600, 20 }, 
     { 601, 900, 30 }, 
     { 901, 1200, 40 } 
     // And so on... 
    }; 

    value_type testValues[] = { 
      -1,     // None 
      0, 299, 300, // [ 0, 300] 
     301, 599, 600, // [301, 600] 
     601, 899, 900, // [601, 900] 
     901, 1199, 1200, // [901, 1200] 
     // And so on... 
    }; 

    for (size_t i = 0; i < sizeof(testValues)/sizeof(testValues[0]); ++i) { 
     const range_t *match = find_range(
      ranges, sizeof(ranges)/sizeof(ranges[0]), testValues[i]); 
     if (match != NULL) 
      printf("%d found at [%d..%d]\n", testValues[i], match->min, 
       match->max); 
     else 
      printf("%d not found\n", testValues[i]); 
    } 
    return EXIT_SUCCESS; 
} 

Should Ausgabe:

-1 not found 
0 found at [0..300] 
299 found at [0..300] 
300 found at [0..300] 
301 found at [301..600] 
599 found at [301..600] 
600 found at [301..600] 
601 found at [601..900] 
899 found at [601..900] 
900 found at [601..900] 
901 found at [901..1200] 
1199 found at [901..1200] 
1200 found at [901..1200] 
Verwandte Themen