如何根据给定值 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;
}
我需要一种方法 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;
}