【问题标题】:Is there are more elegant Solution for a large switch statement?大型 switch 语句是否有更优雅的解决方案?
【发布时间】:2023-03-30 04:33:01
【问题描述】:

我已经将很多范围映射到一个值,例如 0-300 = 10、300-600 = 20、600-900 = 30 ... 2500000-2700000 = 7000 .... 所以我可以做一个真正的大型 switch 语句/if 块,但我想知道是否有更优雅的方法来解决这个小问题。

好的,这里是包含真实数据的表的一小部分:

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

【问题讨论】:

  • O
  • 所以每 300 次你将结果增加 10?您期望 1150 的结果是什么?你确定2500000 => 7000 的结果吗?这与模式不匹配。

标签: objective-c ios optimization switch-statement


【解决方案1】:

摆脱 switch 语句的最常见模式是使用字典。在您的情况下,由于您正在映射范围,因此您将使用范围截止的NSArray。如果您正在处理整数,这就是它的样子:

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];
}

实际上,您希望从 plist 加载 rangeCutoffsvalues,而不是硬编码它们。

【讨论】:

    【解决方案2】:

    你可以使用一张桌子。例如

    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
    };
    

    然后简单地遍历它以找到正确的范围

    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;
         }
    }
    

    如果它是一个非常大的表,你可以使用二进制搜索来代替。

    【讨论】:

    • OP 预期的值从 10 到 7000(甚至更多)。写700行代码来定义table是不合理的。
    • @sch:否则他将如何处理所有可能的病例?它们必须在某处输入。
    • 我使用的值只是示例。这将是一些值,但无论如何我都必须通过 Code/Plist 对它们进行硬编码。
    • 现在很明显范围不遵循某种模式,那么是的,它们必须在某处输入。 (我仍然看到一个模式,但 OP 说这只是表格的一小部分)
    【解决方案3】:

    您可以这样做(C 示例):

    #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;
    }
    

    应该输出:

    -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]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-03
      • 1970-01-01
      • 2011-02-05
      • 2018-04-28
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      • 2020-07-30
      相关资源
      最近更新 更多