I am writing unit tests now and I need to create a specific string.
I have now defined something like this:
private final String at = "#:";
private String error, effect, one, two, three, four;
in setUp (#Before):
error = RandomStringUtils.randomAlphabetic (3);
one = RandomStringUtils.randomAlphabetic (6);
two = RandomStringUtils.randomAlphabetic (8);
three = RandomStringUtils.randomAlphabetic (2);
four = RandomStringUtils.randomAlphabetic (6);
effect = (error + at + one + at + two + at + three + at + four);
The combination of the strings with the pluses looks terribly ugly and amateurish. Is it possible to do it somehow more efficiently using anything else? For example pattern? I dont know. Thanks for help :)
For simplicity, you can also do:
String.join(at, error,one, two, three, four);
You can use the java built-in StringBuilder
StringBuilder sb = new StringBuilder();
sb.append(error);
sb.append(at);
sb.append(one);
...
effect = sb.toString();
If the "#:" is a consistent separator, and you're using Java 8+, you might find that String.join is your friend. This would look something like:
effect = String.join("#:", error, one, two, three, four);
Guessing a little bit from your variable names, but as a little background and just in case it's helpful, if you want/need to use a Stream you can also use Collectors.joining, which could look something like:
List<String> stringParts = ...
stringParts.stream()
.collect(Collectors.joining("#:"));
This will join everything in the list with "#:" as a delimiter. You can also add a constant prefix and/or suffix which might be relevant for your error variable, like:
String error = RandomStringUtils.randomAlphabetic(3);
List<String> stringParts = ...
stringParts.stream()
.collect(Collectors.joining("#:", error, ""));
Related
How to strip a string like this:
String a = "ItemStack{DIAMOND_HELMET x 1,UNSPECIFIC_META:{meta-type=UNSPECIFIC, display-name=PRO, repair-cost=1}}"
I want to get something like
"Diamond_HELMET 1 UNSPECIFIC PRO"
The methods I have tried is just replacing a bunch of strings, but its a pain in the *** and looks awful. Just wondering if anyone have a better solution/option.
Sorry forgot to add my own code :/
String itemStackStringName = "ItemStack{DIAMOND_HELMET x 1, UNSPECIFIC_META:{meta-type=UNSPECIFIC, display-name=PRO, repair-cost=1}}";
String getItemStacks = itemStackStringName.replace("ItemStack","")
.replace("{","").replace("}", "").replace("UNSPECIFIC_META:", "")
.replace("display-name", "").replace("=","")
.replace("meta-type", "").replace("repair-cost1", "")
.replace("x", "").replace(",","");
System.out.println(getItemStacks);
"DIAMOND_HELMET 1 UNSPECIFIC PRO"
It works, but its just a huge mess.
If you know that's the type your strings are going to be, you can go ahead and do something like this:
String arr[] = a.split("\\{");//you get an array of 3 strings
String someFinalString = arr[1].split("x")[0].trim();//you get "DIAMOND_HELMET"
someFinalString += arr[1].split("x")[1].split(",")[0];
arr = arr[2].split("\\=");//you get an array of 4 strings
someFinalString += " " + arr[1].split(",")[0] + " " + arr[2].split(",")[0];
In the future please post what you tried to do. Splitting something like this will always look awful. You can always make it concise later.
Just a proof this works (and you can figure out by yourself how to get lowercase I guess):
I have a string = ab:cd:ef:gh. On this input, I want to return the string ef:gh (third colon intact).
The string apple:orange:cat:dog should return cat:dog (there's always 4 items and 3 colons).
I could have a loop that counts colons and makes a string of characters after the second colon, but I was wondering if there exists some easier way to solve it.
You can use the split() method for your string.
String example = "ab:cd:ef:gh";
String[] parts = example.split(":");
System.out.println(parts[parts.length-2] + ":" + parts[parts.length-1]);
String example = "ab:cd:ef:gh";
String[] parts = example.split(":",3); // create at most 3 Array entries
System.out.println(parts[2]);
The split function might be what you're looking for here. Use the colon, like in the documentation as your delimiter. You can then obtain the last two indexes, like in an array.
Yes, there is easier way.
First, is by using method split from String class:
String txt= "ab:cd:ef:gh";
String[] arr = example.split(":");
System.out.println(arr[arr.length-2] + " " + arr[arr.length-1]);
and the second, is to use Matcher class.
Use overloaded version of lastIndexOf(), which takes the starting index as 2nd parameter:
str.substring(a.lastIndexOf(":", a.lastIndexOf(":") - 1) + 1)
Another solution would be using a Pattern to match your input, something like [^:]+:[^:]+$. Using a pattern would probably be easier to maintain as you can easily change it to handle for example other separators, without changing the rest of the method.
Using a pattern is also likely be more efficient than String.split() as the latter is also converting its parameter to a Pattern internally, but it does more than what you actually need.
This would give something like this:
String example = "ab:cd:ef:gh";
Pattern regex = Pattern.compile("[^:]+:[^:]+$");
final Matcher matcher = regex.matcher(example);
if (matcher.find()) {
// extract the matching group, which is what we are looking for
System.out.println(matcher.group()); // prints ef:gh
} else {
// handle invalid input
System.out.println("no match");
}
Note that you would typically extract regex as a reusable constant to avoid compiling the pattern every time. Using a constant would also make the pattern easier to change without looking at the actual code.
My target is to format next number 01122222222 to this 011-22-22-22-22
First three numbers of number, dash and all next numbers with dash after second one. Already tried:
private String phoneFormat(String phoneNumber){
String regex = "\\B(?=(\\d{3})+(?!\\d))";
String formattedPhone = phoneNumber.replaceAll(regex, Constants.Characters.DASH);
return formattedPhone;
}
but it produce different result.
A regex will do the trick. Replace sets of 2 digits with "-[digit][digit]" as long as you have 3 digits before those.
public static void main(String[] args) {
String s = "01122222222";
System.out.println(s.replaceAll("(?<=\\d{3})(\\d{2})+?", "-$1"));
}
Live Example
O/P :
011-22-22-22-22
PS : This approach should NOT be used in prod environment and has been written solely to please my own stubbornness that this problem can be solved using one regex.
Since at first your question wasn't clear, I had a solution for both Java and Javascript. I'll leave the javascript one in here as well just 'cause :-)
Java 8
First we use substring(0,3) to get the first three numbers. We add - to this, and with the remaining group (x.substring(3)), we split them in groups of two, and we join them together with String.join and use - as the concatenating character.
String test = "01122222222";
String res = test.substring(0,3) + "-";
String[] parts = test.substring(3).split("(?=(?:..)*$)");
res += String.join("-",parts);
System.out.println(res);
Live Example
Pre Java 8
From the comments it became clear that you are not using Java 8, so pre-java8 there are various other solutions. You could use a loop like I have done, and add the last part manually. (Alternatively, you could just create the string with each element in the loop, and take the substring again to remove the last -).
String test = "01122222222";
String res = test.substring(0,3) + "-";
String[] parts = test.substring(3).split("(?=(?:..)*$)");
for(int i = 0; i < parts.length-1; i++){
res += parts[i]+"-";
}
res+=parts[parts.length-1];
System.out.println(res);
Live Example
Javascript
Using the same logic, you could do this in javascript as well. You can run the snippet to see that the result is actually what you expected.
var x = "01122222222";
var res = x.substring(0,3) +"-"+ x.substring(3).split(/(?=(?:..)*$)/).join("-");
console.log(res)
Is it possible to replace() multiple strings at once?
For example:
String X = new String("I will find cookies");
String newX = X.replace(("will", "won't") + ("I", "You"));
System.out.print(newX);
OUTPUT
You won't find cookies
I know what I did was wrong and will create an error but at least you get my idea of "replacing multiples". If it's possible, what would be the better solution to this?
The simplest answer (I can think of) here is:
String newX = X.replace("will", "won't").replace("I", "You");
This will be find for a simple example like this, but if you're trying to do anything bigger (i.e. many more replacements), you'd be wise to look into regular expressions instead.
You can do a chained call of replace() like below:
String X = new String("I will find cookies");
String newX = X.replace("will", "won't").replace("I", "You");
System.out.print(newX);
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?
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));
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.