【问题标题】:How can I map a list of ranges to a single value?如何将范围列表映射到单个值?
【发布时间】:2011-04-03 00:23:10
【问题描述】:

我最近才涉足 iphone 开发和 Objective-c 的世界,所以对于如何实现这样的东西我还是有点迷茫。

我有一个浮点数,我有一个浮点数可以落入的范围列表以及我应该返回的相应值,例如:

10.0 - 14.5 : 1.0
14.5 - 17.0 : 2.0
17.0 - 23.0 : 2.5
23.0 - 32.4 : 4.0

如果我的浮点数是 15.12,我想返回 2.0。

让这件事变得棘手的部分是范围列表很长,我需要从几个这样的范围列表中进行选择,其中任何一个都可能需要稍后更改。简单地说,简单地写几百或几千个if 语句似乎是一个丑陋的解决方案。

【问题讨论】:

    标签: iphone objective-c cocoa cocoa-touch fuzzy-logic


    【解决方案1】:

    如果范围都是相邻的,您可以为此创建一个自定义集合类,并使用两个并行的数字数组来实现它。

    第一个数组中的每个数字都是一个或两个范围的一端:

    • 10.0
    • 14.5
    • 17.0
    • 23.0
    • 32.4

    第二个数组少一个数;这些数字是要映射到的值:

    • 1.0
    • 2.0
    • 2.5
    • 4.0

    您搜索此集合的实现包括将请求的键编号与键数组中的每个数字及其后面的数字进行比较。实现线性搜索是最简单的,至少一开始是这样(您可以稍后在 Instruments 或 Shark 的指导下对其进行优化)。例如,假设这个对象被问到大约 20:

    • 10.0 ≤ 20
    • 14.5 ≤ 20
    • 17.0 ≤ 20

    发现请求的键值在第三个范围内,返回第三个值(2.5)。

    【讨论】:

    • 没有理由你不能。这是一个实现细节;提问者可以实现线性搜索以使其正常工作(至少足够长以编写单元测试来证明这一点),然后如果 Instruments 或 Shark 或计时测试用例确认线性搜索不够快,则将其更改为分区搜索.
    • (之前的评论是针对为什么不使用二分搜索而不是线性搜索的问题。)我看到这个答案被否决了;请给它的人解释一下为什么?
    【解决方案2】:

    基本上你所描述的是Fuzzy Logic

    我给你写了一个模糊逻辑规则类,它应该可以处理你想做的事情。

    特点:

    • 您可以使用我提供的方法轻松添加自己的自定义规则。
    • 您可以使用单个 method 检查值并获取字符串结果(或 nil,如果它不匹配任何规则)。
    • 由于它使用规则,您可以定义任何您希望的间隔时间段。

    添加新规则

    [logic addRule:@"2.0" forLowerCondition:14.5 forUpperCondition:17.0];
    

    示例输出(来自下面的代码):

    Result for 15.20 is: 2.0
    

    这里是代码实现.....

    在您的主目录中:

    FuzzyLogic *logic = [[FuzzyLogic alloc] initWithRule:@"1.0" forLowerCondition:10.0 forUpperCondition:14.5];
    
    [logic addRule:@"2.0" forLowerCondition:14.5 forUpperCondition:17.0];
    [logic addRule:@"2.5" forLowerCondition:17.0 forUpperCondition:23.0];
    
    double input1 = 15.2f;
    
    NSLog(@"Result for %.2lf is: %@", input1, [logic fuzzyResultForValue:input1]);
    
    [logic release];
    

    FuzzyLogic.h:

    #import <Foundation/Foundation.h>
    
    @interface FuzzyLogic : NSObject {
        NSMutableArray *conditions;
    }
    
    - (id) initWithRule:(NSString*)result forLowerCondition:(double)lower forUpperCondition:(double)upper;
    - (void) addRule:(NSString*)result forLowerCondition:(double)lower forUpperCondition:(double)upper;
    - (NSString*) fuzzyResultForValue:(double)input;
    
    @end
    

    FuzzyLogic.m:

    #import "FuzzyLogic.h"
    
    @implementation FuzzyLogic
    
    enum {
        lowerIndex = 0,
        upperIndex,
        resultIndex
    };
    
    - (id) initWithRule:(NSString*)result forLowerCondition:(double)lower forUpperCondition:(double)upper {
        self = [super init];
        if (self != nil) {
            [self addRule:result forLowerCondition:lower forUpperCondition:upper];
        }
        return self;
    }
    
    - (void) addRule:(NSString*)result forLowerCondition:(double)lower forUpperCondition:(double)upper {
    
        NSArray *rule = [[NSArray alloc] initWithObjects:[NSString stringWithFormat:@"%lf",lower],[NSString stringWithFormat:@"%lf",upper],result,nil];
    
        if (conditions == nil) {
            conditions = [[NSMutableArray alloc] initWithObjects:rule,nil];
        } else {
            [conditions addObject:rule];
        }
    }
    
    - (NSString*) fuzzyResultForValue:(double)input
    {
        NSString *returnable = nil;
    
        // Find the result
        for (NSArray *cond in conditions) {
            double lower = [[cond objectAtIndex:lowerIndex] doubleValue];
            double upper = [[cond objectAtIndex:upperIndex] doubleValue];
            if ( (input >= lower && input < upper) ) {
                returnable = [cond objectAtIndex:resultIndex];
                break;
            }   
        }
    
        if (returnable == nil) 
        { NSLog(@"Error: Input met no conditions!");}
        return returnable;
    }
    
    @end
    

    【讨论】:

      猜你喜欢
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 2021-12-07
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 2019-11-26
      • 1970-01-01
      相关资源
      最近更新 更多