Java trim character and whitespaces - java

Reading the annotation on top of Java TestNG test and I have annotation as:
#TestInfo(id={ " C26603", " C10047" })
where TestInfo is just the interface that has id() as String array:
public String[] id() default {};
and C26603 and C10047 are just test ids that I assign.
Here is how test structure looks like (for example):
CASE 1:
#TestInfo(id={ " C26603", " C10047" })
public void testDoSomething() {
Assert.assertTrue(false);
}
Similarly more cleaner case would be:
CASE 2:
#TestInfo(id={ "C26603", "C10047" })
As you can see this case 2 is more clear than the case 1. This case 2 does not have white spaces in test ids.
How do I fetch these ids and make sure that they don't have that C character in beginning and just a pure number? For example, I just want 26603 for my first id and 10047 for 2nd one. There are some spaces in the id array (inside quotes). I want to trim everything of that (like white spaces) and just get the id. I am currently applying for loop to process each id and once I get the pure number, I want to make a 3rd party API call (API expects pure number as input and so removal of C as initial character and other white spaces is important).
Here is what I have tried:
TestInfo annotation = method.getAnnotation(TestInfo.class);
if(annotation!=null) {
for(String test_id: annotation.id()) {
//check if id is null or empty
if (test_id !=null && !test_id.isEmpty()) {
//remove white spaces and check if id = "C1234" or id = "1234"
if(Character.isLetter(test_id.trim().charAt(0))) {
test_id = test_id.substring(1);
}
System.out.println(test_id);
System.out.println(test_id.trim());
}
}
}
Above code gives me C26603 and not 26603 for the case 1. It works for the case 2.
CASE 3:
#TestInfo(id={ " 26603", " 10047" })
For this case, there is no C as beginning character of test id, so the function should be smart enough to just trim white spaces and go ahead.

The simplest approach would be to just remove everything that is not a digit, using the regular expression non-digit character class (\D):
test_id = test_id.replaceAll("\\D", "");

I highly encourage you to debug your method. You will learn a lot.
If you take a look at your if statement here:
if(Character.isLetter(test_id.trim().charAt(0))) {
test_id = test_id.substring(1);
}
When your test_id = " C1234", your condition is true. However, your problem becomes the substring.
ANSWER: trim it!
test_id = test_id.trim().substring(1);

Related

Extra java input validation for strings

I want to make this so that short inputs can still be detected, such as "Londo" and "Lon", but want to keep it small and use it without basically copying and pasting the code, any tips? thank you.
if (Menu.answer1.equals("London"))
{
if (location.equals("London")) {
System.out.print(location + " ");
System.out.print(date + " ");
System.out.print(degrees + "C ");
System.out.print(wind + "MPH ");
System.out.print(winddirection + " ");
System.out.print(weather + " ");
System.out.println("");
}
You can use startsWith()
String city = "London";
if (city.startsWith("Lon")) {
// do something
}
Also if you need to check some substring, you can use contains method:
Menu.answer1 = "London";
Menu.answer1.contains("ondo"); // true
If you want to check against a fixed set of alternatives, you may use a list of valid inputs using contains:
List<String> londonNames = Arrays.asList("London", "Londo", "Lon");
if (londonNames.contains(Menu.answer1)) {
...
}
You can use (case-insensitive) regex to do the same, e.g.:
(?)Lon[a-z]{0,3} where
(?) = case insensitivity
Lon = Initial 3 characters
[a-z]{0,3} = any number of alphabets between 0 and 3
Here's an example:
String regex = "(?)Lon[a-z]{0,3}";
System.out.println("London".matches(regex));
System.out.println("Lond".matches(regex));
System.out.println("Lon".matches(regex));
If the underlying problem is that the user can enter one of several names, and you want to allow abbreviations, then a fairly standard approach is to have a table of acceptable names.
Given the user input, loop through the table testing "does the table entry start with the string typed by the user?" (like one of the previous answers here). If yes, then you have a potential match.
Keep looking. If you get a second match then the user input was ambiguous and should be rejected.
As a bonus, you can collect all names that match, and then use them in an error message. ("Pick one of London, Lonfoo, Lonbar").
This approach has the advantage (compared to a long chain of if-then-else logic) of not requiring you to write more code when all you want to do is have more data.
It automatically allows the shortest unique abbreviation, and will adjust when a once-unique abbreviation is no longer unique because of newly-added names.

Java/Kotlin: Tokenize a string ignoring the contents of nested quotes

I would like to split a character by spaces but keep the spaces inside the quotes (and the quotes themselves). The problem is, the quotes can be nested, and also I would need to do this for both single and double quotes. So, from the line this "'"is a possible option"'" and ""so is this"" and '''this one too''' and even ""mismatched quotes" I would like to get [this, "'"is a possible option"'", and, ""so is this"", and, '''this one too''', and, even, ""mismatched quotes"].
This question has already been asked, but not the exact question that I'm asking. Here are several solutions: one uses a matcher (in this case """x""" would be split into [""", x"""], so this is not what I need) and Apache Commons (which works with """x""" but not with ""x"", since it takes the first two double quotes and leaves the last two with x). There are also suggestions of writing a function to do so manually, but this would be the last resort.
You can achieve that with the following regex: ["']+[^"']+?["']+. Using that pattern you retrieve the indices where you want to split like this:
val indices = Regex(pattern).findAll(this).map{ listOf(it.range.start, it.range.endInclusive) }.flatten().toMutableList()
The rest is building the list out of substrings. Here the complete function:
fun String.splitByPattern(pattern: String): List<String> {
val indices = Regex(pattern).findAll(this).map{ listOf(it.range.start, it.range.endInclusive) }.flatten().toMutableList()
var lastIndex = 0
return indices.mapIndexed { i, ele ->
val end = if(i % 2 == 0) ele else ele + 1 // magic
substring(lastIndex, end).apply {
lastIndex = end
}
}
}
Usage:
val str = """
this "'"is a possible option"'" and ""so is this"" and '''this one too''' and even ""mismatched quotes"
""".trim()
println(str.splitByPattern("""["']+[^"']+?["']+"""))
Output:
[this , "'"is a possible option"'", and , ""so is this"", and , '''this one too''', and even , ""mismatched quotes"]
Try it out on Kotlin's playground!

Extracting Substrings from a List in Java

If I have a parent string (let's call it output) that contains a list of variable assignments like so ...
status.availability-state available
status.enabled-state enabled
status.status-reason The pool is available
And I want to extract the values of each variable in that list given the variable names, ie the substring after the space following status.availability-state, status.enabled-state, and status.status-reason, such that I end up with three different variable assignments making each of the following String comparisons true ...
String availability = output.substring(TODO);
String enabled = output.substring(TODO);
String reason = output.substring(TODO);
availability.equals("available");
enabled.equals("enabled");
reason.equals("The pool is available");
What is the simplest way to do this? Should I even use substring for this?
This is a little tricky because you need to assign the value to a specific variable - you can't just have a map of keys to variables in Java.
I would consider doing this with a switch:
for (String line : output.split('\n')) {
String[] frags = line.split(' ', 2); // Split the line in 2 at the space.
switch (frags[0]) { // This is the "key" of the variable.
case "status.availability-state":
availability = frags[1]; // This assigns the "value" to the relevant variable.
break;
case "status.enabled-state":
enabled = frags[1];
break;
// ... etc
}
}
It's not very pretty, but you don't have too many options.
There seem to be two questions here -- how to parse the string, and how to assign to variables by name.
Tackle the string parsing one step at a time:
first write a program to read one line at a time and output each one in the body of a loop. String.split() or StringTokenizer are two options here.
next enhance this by writing a method to handle one line. The same tools are helpful here, to split on spaces.
You should now have a program that can print name: status.availability-state, value: available for each line of input.
Next, you're asking to programatically assign to variables based on the name of the parameter.
There is no legitimate way to look at a variable's name at runtime (OK, Java 8 reflection has ways, but it shouldn't be used without very good reason).
So, the best you can do is to use a switch or if statement:
switch(name) {
case status.availability-state:
availability = value;
break;
... etc.
}
However, whenever you use switch or if you should think about whether there's a better way.
Is there any reason you can't turn these variables into Map entries?
configMap.add(name,value);
Then to read it:
doSomethingWith(configMap.get("status.availability");
That's what maps are for. Use them.
This is a similar situation to the rookie mistake of using variables called person1, person2, person3... instead of using an array. Eventually they ask "How do I go from the number 25 to my variable person25?" -- and the answer is, you can't, but an array or list makes it easy. people[number] or people.get(number)
A valid alternative is to split the string by \n and add to a Map. Example:
String properties = "status.availability-state available\nstatus.enabled-state enabled\nstatus.status-reason The pool is available";
Map<String, String> map = Arrays.stream(properties.split("\n"))
.collect(Collectors.toMap(s -> s.split(" ")[0], s -> s.split(" ", 2)[1]));
System.out.println(map.get("status.status-reason"));
Should output The pool is available
This loop will match and extract the variables, and you can then assign them as you see fit:
Pattern regex = Pattern.compile("status\\.(.*?)-.*? ([a-z]+)");
Matcher matcher = regex.matcher(output);
while (matcher.find()) {
System.out.println(matcher.group(1) + "=" + matcher.group(2));
}
status\\. matches "status."
(.*?) matches any sequence of characters but isn't greedy, and captures them
-.* matches dash, any chars, space
([a-z]+) matches any string of lower-case letters, and captures them
Here's one way to do it:
Map<String, String> properties = getProperties(propertiesString);
availability = properties.get("availability-state");
enabled = properties.get("enabled-state");
reason = properties.get("status-reason");
// ...
public void getProperties(String input) {
Map<String, String> properties = new HashMap<>();
String[] lines = output.split("\n");
for (String line : lines) {
String[] parts = line.split(" ");
int keyStartIndex = parts[0].indexOf(".") + 1;
int spaceIndex = parts[1].indexOf(" ");
string key = parts[0].substring(keyStartIndex, spaceIndex);
properties.put(key, parts[1]);
}
return properties;
}
This seems to be a bit more straight-forward, in terms of the code that's setting these values, as each value is set to exactly the value from the map, rather than iterating over some list of strings and seeing if it contains a particular value and doing different things based on that.
This is designed with the primary use-case being that the string is created at runtime in memory. If the properties are created in an external file, this code would still work (after creating the desired String in memory), but it may be a better idea to use either a Properties file, or perhaps a Scanner.

How to search the whole string for a specific word?

I have this code which searches a string array and returns the result if the input string matches the 1st characters of a string:
for (int i = 0; i < countryCode.length; i++) {
if (textlength <= countryCode[i].length()) {
if (etsearch
.getText()
.toString()
.equalsIgnoreCase(
(String) countryCode[i].subSequence(0,
textlength))) {
text_sort.add(countryCode[i]);
image_sort.add(flag[i]);
condition_sort.add(condition[i]);
}
}
}
But i want to get those string also where the input string matches not only in the first characters but also any where in the string? How to do this?
You have three way to search if an string contain substring or not:
String string = "Test, I am Adam";
// Anywhere in string
b = string.indexOf("I am") > 0; // true if contains
// Anywhere in string
b = string.matches("(?i).*i am.*"); // true if contains but ignore case
// Anywhere in string
b = string.contains("AA") ; // true if contains but ignore case
I have not enough 'reputation points' to reply in the comments, but there is an error in the accepted answer. indexOf() returns -1 when it cannot find the substring, so it should be:
b = string.indexOf("I am") >= 0;
Check out the contains(CharSequence) method
Try this-
etsearch.getText().toString().contains((String) countryCode[i]);
You could use contains. As in:
myString.contains("xxx");
See also: http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html, specifically the contains area.
Use the following:
public boolean contains (CharSequence cs)
Since: API Level 1
Determines if this String contains the sequence of characters in the CharSequence passed.
Parameters
cs the character sequence to search for.
Returns
true if the sequence of characters are contained in this string, otherwise false
Actually, the default Arrayadapter class in android only seems to search from the beginning of whole words but by using the custom Arrayadapter class, you can search for parts of the arbitrary string. I have created the whole custom class and released the library. It is very easy to use. You can check the implementation and usage from here or by clicking on the link provided below.
https://github.com/mohitjha727/Advanced-Search-Filter
You can refer to this simple example-
We have names " Mohit " and "Rohan" and if We put " M" only then Mohit shows up in search result, but when we put "oh" then both Mohit and Rohan show up as they have the common letter 'oh'.
Thank You.

Java Searching Through a String

So I want to search through a string to see if it contains the substring that I'm looking for. This is the algorithm I wrote up:
//Declares the String to be searched
String temp = "Hello World?";
//A String array is created to store the individual
//substrings in temp
String[] array = temp.split(" ");
//Iterates through String array and determines if the
//substring is present
for(String a : array)
{
if(a.equalsIgnoreCase("hello"))
{
System.out.println("Found");
break;
}
System.out.println("Not Found");
}
This algorithm works for "hello" but I don't know how to get it to work for "world" since it has a question mark attached to it.
Thanks for any help!
Take a look:
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html#contains(java.lang.CharSequence)
String.contains();
To get a containsIgnoreCase(), you'll have to make your searchword and your String toLowerCase().
Take a look at this answer:
How to check if a String contains another String in a case insensitive manner in Java?
return s1.toLowerCase().contains(s2.toLowerCase());
This will also be true for:
war of the worlds, because it will find world. If you don't want this behavior, youll have to change your method like #Bart Kiers said.
Split on the following instead:
"[\\s?.!,]"
which matches any space char, question mark, dot, exclamation or a comma (add more chars if you like).
Or do a temp = temp.toLowerCase() and then temp.contains("world").
You dont have to do this, it's already implemented:
IndexOf and others
You may want to use :
String string = "Hello World?";
boolean b = string.indexOf("Hello") > 0; // true
To ignore case, regular expressions must be used .
b = string.matches("(?i).*Hello.*");
One more variation to ignore case would be :
// To ignore case
b=string.toLowerCase().indexOf("Hello".toLowerCase()) > 0 // true

Categories