3

I've got a set of path strings:

/content/example-site/global/library/about/contact/thank-you.html
/content/example-site/global/corporate/about/contact/thank-you.html
/content/example-site/countries/uk/about/contact/thank-you.html
/content/example-site/countries/de/about/contact/thank-you.html
/content/example-site/others/about/contact/thank-you.html
...

(Often the paths are much longer than this)

As you can see it is difficult to notice the differences immediately. That's why I would like to highlight the relevant parts in the strings.

To find the differences I currently calculate the common prefix and suffix of all strings:

String prefix = getCommonPrefix(paths);
String suffix = getCommonSuffix(paths);
for (String path : paths) {
    String relevantPath = path.substring(prefix.length(), path.length() - suffix.length());
    // OUTPUT: prefix + "<b>" + relevantPath + "</b>" + suffix
}

For the prefix I'm using StringUtils.getCommonPrefix from Commons Lang.

For the suffix I couldn't find a utility (neither in Commons nor in Guava, the later has only one for exactly two strings). So I had to write my own - similar to the one from Commons Lang.

I'm now wondering, if I missed some function in one of the libraries - or if there is an easy way with Java 8 streaming functions?

Tobias Liefke
  • 8,637
  • 2
  • 41
  • 58

2 Answers2

3

Here is a little hack, I do not say it is optimal nor nothing but it could be interesting to follow this path if no other option is available:

String[] reversedPaths = new String[paths.length];
for (int i = 0; i < paths.length; i++) {
    reversedPaths[i] = StringUtils.reverse(paths[i]);
}
String suffix = StringUtils.reverse(StringUtils.getCommonPrefix(reversedPaths));
Tobias Liefke
  • 8,637
  • 2
  • 41
  • 58
Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
  • 1
    I replaced `StringBuilder.reverse` with `StringUtils.reverse`, because it does the same and is a little bit better to read. And I removed the *Solution* headline to take the pressure from me to accept it right away ;-) – Tobias Liefke Nov 22 '15 at 07:18
  • @TobiasLiefke No problem. I did not know StringUtils had such a method. Learning everyday :) – Yassin Hajaj Nov 22 '15 at 10:45
0

You could inverse each path, find the prefix of these inversed strings and inverse said prefix to get a common suffix.
Like this:

String commonSuffix = new StringBuffer(getCommonPrefix(paths.stream().map(path -> new StringBuffer(path).reverse().toString()).collect(Collectors.toList()))).reverse().toString();

I personally do not like this solution a lot, because you create a new StringBuffer for every path in your list. That is how java works some times, but it is at least ugly if not dangerous for performance. You could write you own function

public static String invert(String s) { // invert s using char[] }

if you want.

Aracurunir
  • 625
  • 6
  • 10
  • 1
    You should use `StringBuilder` instead of `StringBuffer` (see http://stackoverflow.com/questions/355089/stringbuilder-and-stringbuffer/355092#355092). Writing my own invert function wouldn't make it much faster (I would only spare the initial `char[]` copy for `new StringBuilder`) . But If you use `StringUtils.inverse` instead and take into account that `getCommonPrefix` is expecting a `String[]` I would say that this a valid solution for Java 8. And I wouldn't blame Java for that, as I don't know a language which offers a helper for every String manipulation you can think of... – Tobias Liefke Nov 22 '15 at 07:30