如何根据给定值 return 评分

How to return ratings based on given values

我需要一种方法 returns 基于给定参数的评级值。评级 class 将评级的上限和下限存储为整数(从 xml 文件中读取)。

到目前为止,我有一个类似于下面代码的方法,但我正在寻找一种 "smarter" 和更有效的方法来获得我的评分。

private int GetRating(Ratings ratings, double rawValue)
    {
        int finalRating = 0;

        if (rawValue <= ratings.Rating_1_upperLimit)
            finalRating = 1;

        if (rawValue >= ratings.Rating_2_lowerLimit && rawValue <= ratings.Rating_2_upperLimit)
            finalRating = 2;

        if (rawValue >= ratings.Rating_3_lowerLimit && rawValue <= ratings.Rating_3_upperLimit)
            finalRating = 3;

        if (rawValue >= ratings.Rating_4_lowerLimit && rawValue <= ratings.Rating_4_upperLimit)
            finalRating = 4;

        if (rawValue >= ratings.Rating_2_lowerLimit)
            finalRating = 5;

        return finalRating;
    }

这可能适用于边界是连续的情况:

    private int GetRating(Ratings ratings, double rawValue)
    {
        int finalRating = 0;

        if (rawValue <= ratings.Rating_1_upperLimit)
            finalRating = 1;

        else if ( rawValue <= ratings.Rating_2_upperLimit)
            finalRating = 2;

        else if( rawValue <= ratings.Rating_3_upperLimit)
            finalRating = 3;

        else if( rawValue <= ratings.Rating_4_upperLimit)
            finalRating = 4;
        else 
            finalRating = 5;

        return finalRating;
    }

我想 "efficient",你的意思是减少重复代码?因为就速度而言,代码无法显着加快。我还假设一个评级的下限等于前一个评级的上限。

您的 Ratings class 只需要存储一个包含 4 个双打的列表,它们是每个评级的边界。假设这些数字分别是 20、40、60、80。

public List<double> Boundaries = new List<double>() { 20, 40, 60, 80 };

所有小于 20 的评分为 1,所有小于 40 的评分为 2,所有小于 60 的评分为 3,所有小于 80 的评分为 4,其他所有评分共 5

您可以过滤掉小于rawValue的数字,然后统计还剩多少。加 1 就是评分:

return ratings.Boundaries.Where(x => rawValue >= x).Count() + 1;

性能在您的代码中不会成为大问题。因此,改进它的唯一方法就是缩短它。然而,没有太多要缩短的,但是如果你有更多的收视率,你可以这样做以便更好地扩展:

public struct Rating
{
    public int Lower { get; set; }
    public int Upper { get; set; }
    public int FinalRating { get; set; }
}

private int GetRating(IEnumerable<Rating> ratings, double rawValue)
{
    int finalRating
    foreach(var rating in ratings)
    {
        int currentRating;
        if(rawValue >= rating.Lower && rawValue <= rating.Upper)
            currentRating = rating.FinalRating;

        Math.Max(currentRating, finalRating);
    }
    return finalRating; 
}

此代码为一系列值分配评级,然后对其进行测试。通过将评级作为 IEnumerable 传递,我们可以对它们进行交互(select 最大评级),而不必为每个新评级引入新的 if。您只需将一个新的评级实例添加到评级 IEnumerable 并使用它。 然而,这将比普通的 if-else 慢,尽管在更大的程序中速度优势被更大的可维护性所抵消。

如果范围密集,即

 ratings.Rating_N_upperLimit == ratings.Rating_N+1_lowerLimit

例如

[1_lower_limit..1_upper_limit)[2_lower_limit..2_upper_limit)...[N-1_lower_limit..N-1_upper_limit)[N_lower_limit..N_upper_limit)

你想要

0     if rawValue < 1_lower_limit
k     if rawValue <= k_lower_limit && rawValue < k_upper_limit
N + 1 if rawValue >= N_upper_limit

那么你可以使用二进制搜索

// Lower limit, must be sorted  
static double[] s_Limits = new double[] {
    10.0,
    20.0,
    30.0,
    40.0,
    50.0,
   100.0,
};

...

private static int GetRating(double rawValue) {
    if (rawValue >= s_Limits[s_Limits.Length - 1])
        return s_Limits.Length;

    int index = Array.BinarySearch(s_Limits, rawValue);

    return index < 0 ? -index - 1: index + 1;
}