Reputation: 1411
I am using StringUtils.abbreviateMiddle(string, middle, targetLength);
to abbreviate string in the middle but using this method cuts off the word. Is there a way such that it will only cut off string at the space nearest to the middle position of the string?
public static String shortenStringMiddle(String string, String middle, int targetLength) {
targetLength = Math.abs(targetLength);
if (string != null && string.length() > targetLength) {
return StringUtils.abbreviateMiddle(string, middle, targetLength);
}
else {
return string;
}
}
Input if applied to this text:
Disease Control in Fish and Shrimp Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques: Proceedings of the SEAFDEC-OIE Seminar-Workshop on Disease Control in Fish and Shrimp Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques, 4-6 December 2001, Iloilo City, Philippines
System.out.println(StringUtils.abbreviateMiddle("Disease Control in Fish and Shrimp Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques: Proceedings of the SEAFDEC-OIE Seminar-Workshop on Disease Control in Fish and Shrimp Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques, 4-6 December 2001, Iloilo City, Philippines", " … ", 220));
Output:
Disease Control in Fish and Shrimp Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques: Procee … aculture in Southeast Asia - Diagnosis and Husbandry Techniques, 4-6 December 2001, Iloilo City, Philippines
The word Proceedings was cut off to Procee and Aquaculture to aculture
My ideal output would be:
Disease Control in Fish and Shrimp Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques: Proceedings … Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques, 4-6 December 2001, Iloilo City, Philippines
I've searched here in SO and similar questions only relates to abbreviate string adding an ellipsis at the end.
Upvotes: 7
Views: 3191
Reputation: 97381
Here's another implementation based on a regular expression:
public static String abbreviateMiddle(String input, String middle, int length) {
if (input != null && input.length() > length) {
int half = (length - middle.length()) / 2;
Pattern pattern = Pattern.compile(
"^(.{" + half + ",}?)" + "\\b.*\\b" + "(.{" + half + ",}?)$");
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
return matcher.group(1) + middle + matcher.group(2);
}
}
return input;
}
With your example text, the following call
System.out.println(abbreviateMiddle(exampleText, " ... ", 220));
will produce
Disease Control in Fish and Shrimp Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques: Proceedings ... Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques, 4-6 December 2001, Iloilo City, Philippines
Upvotes: 3
Reputation: 1742
Try this:
public String abbreviateMiddle(String string, String middle, int targetLength) {
String[] ssplit = string.split(" ");
String first = "";
String second = "";
for (int i = 0; i < ssplit.length; i++) {
if (first.length() < targetLength / 2) {
first += ssplit[i] + " ";
} else {
break;
}
}
for (int i = ssplit.length - 1; i >= 0; i--) {
if (second.length() < targetLength / 2) {
second = ssplit[i] + " " + second;
} else {
break;
}
}
return first + middle + second;
}
If you want the result string to be maximum length but strictly less than targetLength (rather than the above code which returns the minimum string that has a length GREATER than targetLength), use
if (first.length() + ssplit[i].length() < targetLength /2)
and
if (second.length() + ssplit[i].length() < targetLength / 2)
instead.
Upvotes: 1
Reputation: 97381
Here's a rough shot at it. Obviously you could implement cleaner fallback methods for cases where the string doesn't contain sufficient spaces etc., but as a base to start from, it should do just fine.
public static String abbreviateMiddle(String input, String middle, int targetLength) {
if (input == null || input.length() <= targetLength) {
return input;
}
int inputLength = input.length();
int halfTargetLength = (targetLength - middle.length()) / 2;
int startLastSpace = input.substring(0, halfTargetLength).lastIndexOf(" ");
int endFirstSpace = input.indexOf(" ", inputLength - halfTargetLength);
if (startLastSpace != -1 || endFirstSpace != -1) {
return input.substring(0, startLastSpace)
+ middle
+ input.substring(endFirstSpace + 1, inputLength);
}
return input;
}
With your example text, the following call
System.out.println(abbreviateMiddle(exampleText, " ... ", 240));
will return
Disease Control in Fish and Shrimp Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques: Proceedings ... Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques, 4-6 December 2001, Iloilo City, Philippines
Setting the targetLength
to 220 will return
Disease Control in Fish and Shrimp Aquaculture in Southeast Asia - Diagnosis and Husbandry Techniques: ... in Southeast Asia - Diagnosis and Husbandry Techniques, 4-6 December 2001, Iloilo City, Philippines
Upvotes: 3
Reputation: 2970
To elaborate on Vince's comment, you could use indexOf(" ") since a space will represent the end of a word (and thus you will not cut off a word). I would look through, find the number of instances of " " in your input, then estimate how many words to put on either end in order to be at or below your char limit (from the targetLength in your method) and then get the substrings after and below your elected instances of " ". I don't know java so I can't write that code for you though, sorry.
Upvotes: 0