The conversion of numbers to text is a frequently encountered problem for engineers. It manifests in various scenarios, and some of the most prevalent examples include:
- Converting a number to a day of the week
- Converting a number to a month
- Transforming a status into user-friendly text
Now, let's explore some solutions for addressing this problem, using the conversion of a number to a day of the week as an explanatory example.
- IF/Else/Switch
if (value == 1) {
return "MON";
} else if (value == 2) {
return "TUE";
} else if (value == 3) {
return "WED";
} else if (value == 4) {
return "THU";
} else if (value == 5) {
return "FRI";
} else if (value == 6) {
return "SAT";
} else if (value == 7) {
return "WED";
}
return "You are on moon";
}
- Maps
Map<Integer, String> dayOfWeek = new HashMap<>() {
{
int index = 1;
put(index++, "MON");
put(index++, "TUE");
put(index++, "WED");
put(index++, "THU");
put(index++, "FRI");
put(index++, "SAT");
put(index++, "SUN");
}
};
return dayOfWeek
.getOrDefault(value, "You are on moon");
}
This solution appears to be an improvement and can be considered a good option, especially when the key is dynamic. However, it is important to note that maintaining this solution can become challenging over time.
- Enums
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
private static final DayOfWeek[] ENUMS = DayOfWeek.values();
public static DayOfWeek of(int dayOfWeek) {
return ENUMS[dayOfWeek - 1];
}
}
- Choice Format
double[] limits = {1, 2, 3, 4, 5, 6, 7};
String[] formats = {"Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"};
ChoiceFormat form = new ChoiceFormat(limits, formats);
return form.format(value);
}
This solution solves the problem by employing a straightforward approach: using pairs of arrays or vectors to map numbers to their corresponding strings.
At first glance, it may not seem particularly remarkable, resembling a Map structure where the keys are represented by one array and the values by another. However, the true test begins when we pass values that are not present in the array.
Now, let's speculate. What do you think this function would return if we were to pass 0 or 100? One possibility could be "Undefined," which would hold true if this were JavaScript. Another option could be null or a NullPointerException, which is a close guess given your familiarity with Java. However, this is where the solution gets interesting.
Lets look at the output for 1/2/0/100
1 -> Mon 2 -> Tue 0 -> Mon 100 -> Sun
The output obtained from this solution provides some valuable insights into how ChoiceFormat operates. For example, when we pass 0, it returns "Monday," and when we pass 100, it returns "Sunday."
Based on these results, you might start getting an idea of how ChoiceFormat functions. It relies on a few key elements:
- Ascending limits array: The limits array is arranged in ascending order, defining the intervals.
- Format array: This array has the same size as the limits array and contains the corresponding text representations for each interval.
- Interval Behaviour: This values in limit array represent half-open interval, meaning that the lower limit is inclusive while upper limit is exclusive.
These factors play a crucial role in determining the appropriate text representation based on the input value within the defined intervals.
Lets look at half-open interval match with below function
double[] limits = {1, 6};
String[] formats = {"WeekDay", "Weekend"};
ChoiceFormat form = new ChoiceFormat(limits, formats);
return form.format(value);
}
This particular implementation exhibits an interesting behavior: for values less than 5, the function returns "Weekday," while for values 6 and above, it returns "Weekend."
Isn't it fascinating how ChoiceFormat manages to accomplish this range-based search and deliver the appropriate result? It's remarkable how this small utility class can perform such a useful trick.
Let's consider one more simple example before delving into the greater capabilities of this utility class.
double[] limits = {1, 2, 5, 6};
String[] formats = {"Monday Blues", "WorkHard", "It is Friday!!", "Relax"};
ChoiceFormat form = new ChoiceFormat(limits, formats);
return form.format(value);
}
double[] limits = {0, 1, 2};
String[] formats = {"No files", "One files", "Many files"};
ChoiceFormat form = new ChoiceFormat(limits, formats);
return form.format(value);
}
System.out.println("Found " + files(100)); //Found Many files
System.out.println("Found " + files(0));//Found No files
System.out.println("Found " + files(1));//Found One files
ChoiceFormat form = new ChoiceFormat(format);
return form.format(value);
}
String format = "0#no files | 1#one file |2# two files |3< more than 2 ";
System.out.println(formatMessage(format, 2)); //two files
System.out.println(formatMessage(format, 10)); //more than 2
System.out.println(formatMessage(format, 0)); //no files
System.out.println(formatMessage(format, 1)); //one file
This example showcases the power of advanced string interpolation by utilizing rules embedded within the format string.
By leveraging this technique, we can define rules directly within the format string itself, which provides a flexible and concise approach to handle various scenarios.
- Parameterised Conditional Log message
Multiple ways to do this, lets look at few example.
double[] priceLimits = {0.0, 10.0, 50.0, 100.0};
String[] priceFormats = {
"The item is not available",
"The item is on sale for {0}",
"The item is moderately priced at {0}",
"The item is expensive at {0}"
};
return new ChoiceFormat(priceLimits, priceFormats);
}
return new ChoiceFormat(
"0#The item is not available |10#The item is on sale for {0} |50#The item is moderately priced at {0} |100#The item is expensive at {0}");
}
String rules = String.join(" |",
"0#The item is not available",
"10#The item is on sale for {0}",
"50#The item is moderately priced at {0}",
"100#The item is expensive at {0}");
return new ChoiceFormat(rules);
}
ChoiceFormat can be created using any of the methods mentioned above, each with its own advantages and considerations. However, some methods may be easier to maintain and less error-prone than others.
Among the options, if I were to choose one, I would prefer using the last method demonstrated, which involves using string rules. This method provides greater flexibility and simplicity in defining the rules for the ChoiceFormat. By using string rules, you can easily specify the mappings between input values and their corresponding text representations in a concise and readable manner. This approach often results in code that is easier to understand, modify, and maintain.
Above format can be used as below
ChoiceFormat priceFormat = usingStringRules();
double price = 120;
Object[] formatArguments = {price};
String formattedPrice = MessageFormat.format(priceFormat.format(price), formatArguments);
System.out.println(formattedPrice); // The item is expensive at 120
Just imaging how this capability can be used by logging framework !
ChoiceFormat empowers to amplify the range of choices available for message formatting. By incorporating ChoiceFormat into your code, you can introduce a multitude of options, enriching the formatting possibilities.
The versatility of ChoiceFormat allows you to define and customize a wide array of choices, each with its own designated format. This flexibility enables you to create dynamic and adaptive messages that cater to different input values.
With ChoiceFormat at your disposal, you can enhance your message formatting capabilities, opening up new avenues for crafting comprehensive and adaptable output.