Is there a short way to do this?
public static string RatingCalculator(int input)
{
if (input < 10)
{
return string.Empty;
}
if (input > 10 && input < 20)
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" />";
}
if (input > 21 && input < 40)
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" />";
}
if (input > 41 && input < 70)
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" />";
}
if (input > 11 && input < 120)
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star_empty.png\" alt=\"-\" />";
}
else
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" />";
}
}
Look at the common parts and try to extract them.
Your Full Star Image Label Never Changes The Blank Star Image Tag never changes so you can extract both of them for reading into variables.
The same goes for the format string, there will always be "5 consecutive star types"
What about
string fs = @"<img src=\"/images/star.png\" alt=\"*\" />"; //Full Star
string es = @"<img src=\"/images/star_empty.png\" alt=\"-\" />"; //Empty Star
string format = @"{0}{1}{2}{3}{4}";
if(input < 10)
return string.Empty;
else if(input < 20)
return string.Format(format, fs, es, es, es, es);
else if(input < 40)
return string.Format(format, fs, fs, es, es, es);
else if(input < 70)
return string.Format(format, fs, fs, fs, es, es);
else if(input < 120)
return string.Format(format, fs, fs, fs, fs, es);
else
return string.Format(format, fs, fs, fs, fs, fs);
Alternatively you can use the string builder
string fs = @"<img src=\"/images/star.png\" alt=\"*\" />"; //Full Star
string es = @"<img src=\"/images/star_empty.png\" alt=\"-\" />"; //Empty Star
StringBuilder sb = new StringBuilder(fs);
//No need for `sb.Append (input > 10 ? fs : es);` as we'll test "input < 10" in the return statement.
sb.Append (input > 20 ? fs : es);
sb.Append (input > 40 ? fs : es);
sb.Append (input > 70 ? fs : es);
sb.Append (input > 120 ? fs : es);
return (input < 10) ? string.Empty : sb.ToString();
a source to share
That many string literals in your code are bound to look horribly ugly. Also, I'm not sure why the gaps in the values ββare volatile (or even not growing regularly), but that's not a big problem.
Try the following:
public static string RatingCalculator(int input)
{
int numStars;
if (input < 10)
return string.Empty;
else if (input < 20)
numStars = 1;
else if (input < 40)
numStars = 2;
else if (input < 70)
numStars = 3;
else if (input < 120)
numStars = 4;
else
numStars = 5;
var sb = new StringBuilder();
for (int i = 0; i < numStars; i++)
sb.Append("<img src=\"/images/star.png\" alt=\"*\" />");
for (int i = numStars; i < 5; i++)
sb.Append("<img src=\"/images/star_empty.png\" alt=\"-\" />");
return sb.ToString();
}
a source to share
Sorry for posting a JavaScript solution (tested on Mozilla Rhino), but I don't know there is much C # and I find the algorithm interesting here.
var rating = function(input) {
var star = '<img src="/images/star.png" alt="*" />',
empty = '<img src="/images/star_empty.png" alt="*" />',
steps = [10, 20, 40, 70, 120],
max = steps.length;
for (var i=0; i<max; i++) {
if (input > steps[i]) {
print(star);
} else {
print(empty);
}
}
};
Maybe it helps somehow.
a source to share
public static string RatingCalculator(int input)
{
if (input < 10)
{
return string.Empty;
}
else if (input < 20)
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" />";
}
else if (input < 40)
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" />";
}
else if (input < 70)
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star_empty.png\" alt=\"-\" /><img src=\"/images/star_empty.png\" alt=\"-\" />";
}
else if (input < 120)
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star_empty.png\" alt=\"-\" />";
}
else
{
return "<img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" /><img src=\"/images/star.png\" alt=\"*\" />";
}
}
Not much shorter, but much better readability.
a source to share
public static string RatingCalculator(int input)
{
int nStars = 0;
if (input < 10)
return string.Empty;
else if (input < 20)
nStars = 1;
else if (input < 40)
nStars = 2;
else if (input < 70)
nStars = 3;
else if (input < 120)
nStars = 4;
else
nStars = 5;
StringBuilder sb = new StringBuilder();
for(int i = 0; i < nStars; i++)
sb.Append("<img src=\"/images/star.png\" alt=\"*\" />");
for(int i = nStars; i < 5; i++)
sb.Append("<img src=\"/images/star_empty.png\" alt=\"-\" />");
return sb.ToString();
}
a source to share
I've tried a loop, for example (note that the logic is off when I abandoned the solution):
public static string RatingCalculator(int input)
{String rating = "";
for(i=0;i<120;i+=10)
{
if(input > i)
rating += "<img src=\"/images/star.png\" alt=\"*\" />";
else
rating += "<img src=\"/images/star_empty.png\" alt=\"-\" />";
}
return rating;
}
But then I noticed non-linear growth in ratings 10,20,40,70, etc.
Using the above answer, you can shorten it and make it more readable by splitting the lines with:
String star = "<img src=\"/images/star.png\" alt=\"*\" />";
String emptyStar = "<img src=\"/images/star_empty.png\" alt=\"-\" />";
What's added to the answer above:
if (input < 10)
{
return string.Empty;
}
else if (input < 20)
{
return star+emptyStar+emptyStar+emptyStar+emptyStar;
}
...
a source to share
I would do something like this:
const string Star = "<img src=\"/images/star.png\" alt=\"*\" />";
const string Star_Empty = "<img src=\"/images/star_empty.png\" alt=\"-\" />";
public static string RatingCalculator(int input)
{
if (input < 10)
{
return string.Empty;
}
else if (input > 10 && input < 20)
{
return string.concat(Star, Star_Empty, Star_Empty, Star_Empty, Star_Empty);
}
else if (input > 21 && input < 40)
{
return string.concat(Star, Star, Star_Empty, Star_Empty, Star_Empty);
}
else if (input > 41 && input < 70)
{
return string.concat(Star, Star, Star, Star_Empty, Star_Empty);
}
else if (input > 11 && input < 120)
{
return string.concat(Star, Star, Star, Star, Star_Empty);
}
else
{
return string.concat(Star, Star, Star, Star, Star);
}
}
a source to share
int starCount;
if (input < 10)
return string.Empty;
else if (input < 20)
starCount = 1;
else if (input < 40)
starCount = 2
else if (input < 70)
starCount = 3;
else if (input < 120)
starCount = 4;
else
starCount = 5;
StringBuilder build = new StringBuilder();
int i;
for(i = 0; i < starCount; i++)
build.Append("<img src=\"/images/star.png\" alt=\"*\" />");
for(; i < 5; i++)
build.Append("<img src=\"/images/star_empty.png\" alt=\"*\" />");
return build.ToString();
Still not very good, but if you rationalize your input (so that it doesn't jump by arbitrary sums), you can get starCount from regular integer division.
a source to share
public static string RatingCalculator(int input)
{
if (input > 120)
{
return GetStart(5);
}
if (input > 70)
{
return GetStars(4);
}
if (input > 40)
{
return GetStars(3);
}
if (input > 20)
{
return GetStars(2);
}
if (input > 10)
{
return GetStars(1);
}
else
{
return string.Empty;
}
}
//populate dictionary with values in your class ctor
private static IDictionary<int, string> images=new Dictionary<int,string>();
private static string GetStars(int stars)
{
if(images.ContainsKey(stars))
return images[stars];
return string.Empty;
}
a source to share
if (input < 10) return string.Empty;
int noOfStars = input >= 120 ? 5 : Math.Min(input / 10, 4);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5; i++)
{
sb.Append(
string.Format("<img src=\"/images/{0}\" alt=\"*\" />",
i < noOfStars ? "star" : "starEmpty")
);
}
return sb.ToString();
a source to share