J'ai besoin d'une méthode qui renvoie une valeur de notation basée sur l'argument donné. La classe Ratings stocke les limites supérieure et inférieure d'une note sous forme d'entiers (lus à partir d'un fichier xml).
Jusqu'à présent, j'ai une méthode similaire au code ci-dessous, mais je recherche une méthode "plus intelligente" et plus efficace pour obtenir ma note.
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; }
4 Réponses :
Cela peut fonctionner si les limites sont continues:
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; }
Je suppose que par "efficace", vous voulez dire moins de code dupliqué? Parce qu'en termes de vitesse, le code ne pouvait pas être accéléré de manière significative. Je suppose également que la limite inférieure d'une note est égale à la limite supérieure de la précédente.
Votre classe Notes
a juste besoin de stocker une liste de 4 doubles, qui sont les limites de chaque note. Supposons que ces nombres soient respectivement 20, 40, 60, 80.
return ratings.Boundaries.Where(x => rawValue >= x).Count() + 1;
Tout ce qui est inférieur à 20 a une cote de 1, tout ce qui est inférieur à 40 a une cote de 2, tout moins de 60 a une cote de 3, tout ce qui est inférieur à 80 a une cote de 4, tout le reste a une cote de 5.
Vous pouvez filtrer les nombres inférieurs à rawValue code> et comptez combien il en reste. Et ce plus 1 est la note:
public List<double> Boundaries = new List<double>() { 20, 40, 60, 80 };
Les performances ne seront pas vraiment un problème dans votre code. Par conséquent, le seul moyen de l'améliorer serait de le raccourcir. Cependant, il n'y a pas grand-chose à raccourcir, mais vous pouvez le faire comme ceci pour être en mesure de mieux évoluer si vous avez plus de notes sur la route:
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; }
Ce codé attribue une note à une plage de valeurs qui sont ensuite testées. En passant les notes comme un IEnumerable, nous pouvons interagir dessus (et sélectionner la plus grande note), sans avoir à introduire un nouveau si pour chaque nouvelle note. Il vous suffit d'ajouter une nouvelle instance de notation aux notes IEnumerable et de dîner avec elle. Cela va cependant être plus lent que le simple if-else, bien que dans les plus gros programmes, l'avantage de la vitesse soit contrebalancé par la maintenabilité beaucoup plus grande.
Dans le cas où les plages sont denses, c'est-à-dire
// 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; }
Par exemple
0 if rawValue < 1_lower_limit k if rawValue <= k_lower_limit && rawValue < k_upper_limit N + 1 if rawValue >= N_upper_limit
et que vous voulez
[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)
alors vous pouvez utiliser la recherche binaire :
ratings.Rating_N_upperLimit == ratings.Rating_N+1_lowerLimit
Pour commencer, vous devez refactoriser votre code. Les notes doivent être un ensemble de classes de notation. La classe de notation doit contenir des propriétés supérieures et inférieures. P.s. lorsque vous voulez nommer des propriétés avec des nombres - vous faites quelque chose de mal.
Je parierais que l'efficacité de ce code ne sera jamais un problème et qu'il n'y a aucun moyen efficace de le rendre (inutilement) plus efficace de toute façon.
Que montre le profileur? Où est le point faible?
Avez-vous des
notes.Rating_N_upperLimit == notes.Rating_N + 1_lowerLimit
(c'est-à-dire pas de trous ) avec des plages?