I am fairly new to programming and regex is very confusing. I am trying to identify a data line that consists of 3 doubles with spaces in between for example:
500.00 56.48 500.00
I have tried this:
data.matches("^[0-9]+\\.[0-9]+\\s[0-9]+\\.[0-9]+\\s[0-9]+\\.[0-9]+$")
But this doesn't recognize the line. What am I doing wrong?
Don't do it the way you have tried.
Although the regex pattern you have used works for the numbers you have used, it will fail for a wide range of numbers e.g. .5 or 5.6E2 which are also double numbers.
Given below is the demo with your data and pattern:
public class Main {
public static void main(String[] args) {
String data = "500.00 56.48 500.00";
System.out.println(data.matches("^[0-9]+\\.[0-9]+\\s[0-9]+\\.[0-9]+\\s[0-9]+\\.[0-9]+$"));
}
}
Output:
true
However, it will fail to give you the expected result in the following case:
public class Main {
public static void main(String[] args) {
String data = ".5 5.6E2 500.00";
System.out.println(data.matches("^[0-9]+\\.[0-9]+\\s[0-9]+\\.[0-9]+\\s[0-9]+\\.[0-9]+$"));
}
}
Output:
false
Even though .5 and 5.6E2 are valid double numbers, your pattern failed to recognize them.
The recommended way:
You should split the data line on whitespace and try to parse each number using Double#parseDouble e.g.
public class Main {
public static void main(String[] args) {
String data = "500.00 56.48 500.00";
System.out.println(matches(data));
data = ".5 5.6E2 500.00";
System.out.println(matches(data));
data = ".5 500.00";
System.out.println(matches(data));
data = ".5 abc 500.00";
System.out.println(matches(data));
}
static boolean matches(String data) {
String[] nums = data.split("\\s+");
boolean match = true;
if (nums.length == 3) {
for (String num : nums) {
try {
Double.parseDouble(num);
} catch (NumberFormatException e) {
match = false;
break;
}
}
} else {
match = false;
}
return match;
}
}
Output:
true
true
false
false
Improve your regex by observing a few things:
[0-9] is the same as \d
you're looking for the same pattern, thrice
So, let's do that:
three times:
one or more numbers, optionally followed by
a period and then one or more numbers, optionally followed by
white space
Which means:
(...){3} where ... is:
\d+, optionally followed by
(\.\d+)? (i.e. zero-or-once), optionally followed by
\s* (zero-or-more)
Putting that all together, and remembering to use proper string escaping:
data.matches("^(\\d+(\\.\\d+)?\\s*){3}$")
You can see this working over on https://regex101.com/r/PGxAm9/1, and keeping regex101 bookmarked for future debugging is highly recommended.
Related
Since users are focused more on minor loop holes than requirement, I am giving actual working code (replacing) for which I need junit test case.
import java.util.*;
public class FirstNonRepeatingCharacterStream {
List<Character> chars = new ArrayList<>();
boolean[] repeated = new boolean[256];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
FirstNonRepeatingCharacterStream tester =
new FirstNonRepeatingCharacterStream();
while (true) {
Character ch = new Character(sc.next().charAt(0));
Character output = tester.firstNonRepeatingCharStream1(ch);
System.out.println(output);
}
}
public Character firstNonRepeatingCharStream1(Character x) {
if (x == null) {
return x;
}
Character output = null;
if (!repeated[x]) {
if (!chars.contains(x)) {
chars.add(x);
} else {
chars.remove(new Character(x));
repeated[x] = true;
}
}
if (chars.size() != 0) {
output = new Character(chars.get(0));
}
return output;
}
}
User enters one character at a time.
input a -> output a
input b -> that means input ab as it's stream -> output a
input a -> that means input aba as it's stream -> output b
input c -> that means input abac as it's stream -> output b
input b -> that means input abacb as it's stream -> output c
input a -> that means input abacba as it's stream -> output c
input d -> that means input abacbad as it's stream -> output c
Please let me know how to write unit test which should comply with main method. Not necessary to have while loop in junit test case.
thanks in advance.
This sounds like it would mostly boil down to coming up with "mean" test strings to try and hit various edge cases in your code:
String testStrings[] {
null,
"", // empty string
"a", // easiest possible string with a match
"aa", // easiest possible string with no match
"aba", // slightly less easy string with a match
"aaaaa", // no match on N instances of a character
"aaaaab", // match on end of N instances of a character
"baaaaa", // match at beginning of N instances of a character
"aabaaa", // match in the middle of N instances of a character
"abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba", // harder string where the unique letter is in the middle (z)
"abcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcb", // harder string where the unique character is at the front (a)
"bcdefghijklmnopqrstuvwxyzzyxwvutsrqponmlkjihgfedcba", // harder string where the unique character is at the back
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy" // other harder string... etc.
};
You then develop a similar array of expected output, and then you blaze through all of your cases in a single for(int i = 0;...) loop.
Another way of developing test input would be to generate test strings algorithmically, such that all the characters occur in pairs in one of three strategies (aabbcc, abccba, abcabc), then poke out the first character, then the last character, then one in the middle (you check which character you're removing first and that becomes your test value).
Lots of different ways to skin this cat.
PS: Your current code will break with null or any character whose "integer" value is greater than 255. Lots of kooky Unicode characters out there... I seem to recall hearing that several dead and fictional languages are now in Unicode (Ancient Egyptian, JJR Tolkien's Elvish, Klingon, etc), to say nothing of the CJKV range (Chinese, Japanese, Korean, Vietnamese). Lots of "code points" out there beyond 256.
I solved it myself.
class FirstNonRepeatingCharacterStreamTest3 {
private static FirstNonRepeatingCharacterStream tester;
#BeforeAll
static void setUpBeforeClass() throws Exception {
tester = new FirstNonRepeatingCharacterStream();
}
#DisplayName("MyTest")
#ParameterizedTest(name = "{index} => input={0}, output= {1}")
#CsvSource({
"'a', 'a'",
"'b', 'a'",
"'a', 'b'",
"'c', 'b'",
"'b', 'c'",
"'a', 'c'",
"'d', 'c'"
})
public void testFirstNonRepeatingCharStream101(Character input, Character output) {
Character actual = tester.firstNonRepeatingCharStream1(input);
assertEquals(output, actual);
}
}
I need to create a recursive method that takes a String parameter.
I need to verify that the first letter in the string is a lowercase character, and then verify that everything that comes after the first letter is a number.
So it should be like this a1234.
I've tried creating a base case, smaller base case, and a general case, but can't seem to figure out the right way to style it:
public void digitCheck(String s) {
if () //To Check that first character is a letter
else if ()To check that everything after the first letter is a number
else //Invalid
}
I need the code to report whether it's a valid string if the first character is a lower case letter and everything after that is a number.
Example:
a123 -> valid.
ab123 -> invalid.
Use the String.matches() method:
boolean valid = s.matches(".\\d+");
For solving this problem with recursion for your pattern you can do:
start from the end and
check the last element
remove the last element
call all remaining part
It should be checking until one element will be passed to the method -> make final validation if it is a lower letter.
Also, StringUtils class is used from commons lang library.
Here is code snippet:
public class StringValidationDemo {
public boolean validateStringRecursive(String str) {
if (str.length() == 1) {
return StringUtils.isAlpha(str) && StringUtils.isAllLowerCase(str);
}
String lastIndex = str.substring(str.length() - 1);
return StringUtils.isNumeric(lastIndex)
&& validateStringRecursive(str.substring(0, str.length() - 1));
}
public static void main(String[] args) {
List<String> words = Arrays.asList("a123", "ab123", "123ab", "A123", "aaa", "123");
StringValidationDemo demo = new StringValidationDemo();
for (String word : words) {
System.out.printf("validation for: %s = %s\n",
word, demo.validateStringRecursive(word));
}
}
}
Output:
validation for: a123 = true
validation for: ab123 = false
validation for: 123ab = false
validation for: A123 = false
validation for: aaa = false
validation for: 123 = false
I think you could ommit the first character in the string, and then just check with Integer.parseInt(String). so it would look something like:
public static boolean isNumeric(String strNum) {
try {
double d = Integer.parseInt(String);
} catch (NumberFormatException | NullPointerException nfe) {
return false;
}
return true;
}
public void DoStuff(String string){
if (isNumeratic(string.substring(1)) //ommits first
{
///yourstuff
}
}
This question already has answers here:
Split the string on forward slash
(4 answers)
Closed 2 years ago.
I really need a regex expert:
I need a regex expression (in java) for splitting this examples:
Hello/World (word/word) => Hello,World
Hello/12 (word/number) => Hello,12
15/Hello (number/word) => 15,Hello
12/17 (number/number) => 12/17 (Do not split)
Update:
This is what I tried but it also mark the number/number option
https://regex101.com/r/zZ9nO5/2
Thanks
It might not be the most elegant solution but for your requirement you can do it like that:
(([a-zA-Z]+?)/([a-zA-Z]+))|(([a-zA-Z]+?)/([\d]+))|(([\d]+?)/([a-zA-Z]+))
It's a check for word / word, word / number and number / word
replace with the corresponding groups found \2\5\8,\3\6\9
A simple java program for that would be:
public static void main(String[] args) {
String[] stringArray=new String[]{"Hello/World","Hello/12","15/Hello","12/17"};
for(String s:stringArray) {
System.out.println(s.replaceAll("(([a-zA-Z]+?)/([a-zA-Z]+))|(([a-zA-Z]+?)/([\\d]+))|(([\\d]+?)/([a-zA-Z]+))", "$2$5$8,$3$6$9"));
}
}
Result is:
Hello,World
Hello,12
15,Hello
12/17
Slightly different approach, but you could check the characters in the String to see that they all are either a number or a forward slash, and then split if necessary:
public static void main(String[] args) {
String[] strArray = new String[]{"Hello/World", "Hello/12", "15/Hello", "12/17"};
for(String str: strArray){
if(checkIfValid(str)){
System.out.println(str);
}
else{
System.out.println(str.replace("/", ","));
}
}
}
public static boolean checkIfValid(String str) {
for (int i = 0; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i)) && str.charAt(i) != '/') {
return false;
}
}
return true;
}
Output:
Hello,World
Hello,12
15,Hello
12/17
This might help if Hello12/15 is not supposed to be split.
A little more context would be nice but as I understand it, you get a string with a single '/' in the middle and you either replace the '/' with ',' or you dont if it has numbers on both sides.
So i would do something like this:
public class MyClass {
public static void main(String args[]) {
String mystring = "12/25";
if(!mystring.matches("^\\d+\\/\\d+$"))
mystring = mystring.replace("/", ",");
System.out.println(mystring);
}
}
If that is what you wanted to do here, then I belive its less complicated and also quicker than a big regex destinguishing between all 4 cases.
I'm trying to find out if the input of the user is decimal or fraction or mixed fraction and when there is a decimal with fraction I would like to replace the decimal to a whole number so that it would be a proper mixed fraction
for example:
input: 2.23 1/2
expected output: 2 1/2
public class DecimalOrFraction {
public static void main(String args[]){
String partOfString;
String[] s = { "0000.2","2","2.222 1/2","1 2/2", "0"};
for (int x = 0 ;x<s.length;x++) {
if(s[x].matches("[1-9]{1}\\d{0,3}([.]\\d{1,3}\\s{0,1})?")){
System.out.println(x+") "+Float.valueOf(s[x])+" ---- Decimal");
}
else if(s[x].matches("[1-9]{1,5}([.]\\d{1,3})?\\s[1-9]{1}\\d{0,2}([/]\\d{0,3})?")){
partOfString = s[x].substring( s[x].lastIndexOf("."), s[x].lastIndexOf(" ")); //HAVING AN ERROR
s[x] = s[x].replace(partOfString," ");
System.out.println(x+") "+s[x]+" ---- Fraction");
}
else if(s[x].matches("[1-9]\\d{0,4}[/]\\d{0,3}")){
System.out.println(x+") "+s[x]+" ---- also Fraction");
}
else{
System.out.println(x+") "+s[x]+" ---- ERROR/Zero");
}
}
}
}
Is there another way to make this work without any error??
The error occurs because there is no dot in "1 2/2" to take the index of.
Since the matching uses RegEx, why not use RegEx for the replacement as well?
Here's a pass at refactoring the whole thing.
private static final Pattern DECIMAL = Pattern.compile("\\d*\\.?\\d+");
private static final Pattern FRACTION = Pattern.compile("\\.\\d+(\\s+\\d+/\\d+)");
public static void main(String args[]) {
String[] samples = {"0000.2", "2", "2.222 1/2", "1 2/2", "0"};
for (String sample : samples) {
if (DECIMAL.matcher(sample).matches()) {
float decimal = Float.parseFloat(sample);
System.out.println(decimal + (decimal == 0 ? "\tERROR/Zero" : "\tDecimal"));
}
else {
String fraction = FRACTION.matcher(sample).replaceFirst("$1");
System.out.println(fraction + "\tFraction");
}
}
}
if you can ONLY have at most two separate parts then you can use String.split() and split on a " " white space. Then if you have two parts it's easier to work with. If you have one, again, simple conditionals. I don't think there's a need for this much messy regex.
Alterantively, if you have more than one whitespace, simply call each resulting split string against a regex for either of your two cases and handle that way.
I am new to write regular expressions so please help.
I want to match this pattern (in Java):
"ABC",010,00,"123",0,"time","time",01,00, 10, 10,88,217," ",," "
the data I get will always be in the above format with 16 values. But the format will never change.
I am not looking for parsing as this can be parsed by java split too.
I will have large chunks of these data so want to capture the first 16 data points and match with this pattern to check if I received it correctly else ignore.
so far I have only tried this regex:
^(\".\"),.,(\".\"),.,(\".\"),(\".\"),.,.,.,.,.,.,(\".\"),.,(\".\")$
I am still in the process of building it.
I just need to match the pattern from a given pool. I take first 16data points and try to see if it matches this pattern else ignore.
Thanks!!
This should do the trick. Keep in mind that he doesn't care what order the data points occur in (ie. they could all be strings or all numbers).
(\s?("[\w\s]*"|\d*)\s?(,|$)){16}
You can try it out here.
Please find in the below code comprising comma separated evaluation for String, Number and Decimal.
public static void commaSeparatedStrings() {
String value = "'It\\'s my world', 'Hello World', 'What\\'s up', 'It\\'s just what I expected.'";
if (value.matches("'([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.]+'(((,)|(,\\s))'([^\'\\\\]*(?:\\\\.[^\'\\\\])*)[\\w\\s,\\.]+')*")) {
System.out.println("Valid...");
} else {
System.out.println("Invalid...");
}
}
/**
*
*/
public static void commaSeparatedDecimals() {
String value = "-111.00, 22111.00, -1.00";
// "\\d+([,]|[,\\s]\\d+)*"
if (value.matches(
"^([-]?)\\d+\\.\\d{1,10}?(((,)|(,\\s))([-]?)\\d+\\.\\d{1,10}?)*")) {
System.out.println("Valid...");
} else {
System.out.println("Invalid...");
}
}
/**
*
*/
public static void commaSeparatedNumbers() {
String value = "-11, 22, -31";
if (value.matches("^([-]?)\\d+(((,)|(,\\s))([-]?)\\d+)*")) {
System.out.println("Valid...");
} else {
System.out.println("Invalid...");
}
}