I am working on a personal project and I want to take in userinput that looks like this :
1.0+2.5+3--4
and format it to something like this :
1.0 + 2.5 + 3 - -4
so far I am using the .replace("+") to .replace(" + ") and doing that for all of the operands but the problem is it makes the user input into this:
1.0 + 2.5 + 3 - - 4
Is there a way that I can make it with the negative signs. I want to do this so I could parse the numbers into doubles and add and subtract them later on.
my code for it :
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringMan {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String check = "-a1 +a2 + a3 +-a5";
check = check.replace("--", "+");
System.out.println(check);
Pattern pattern = Pattern.compile("\\s+");
Matcher matcher = pattern.matcher(check);
boolean expr = matcher.find();
String str = matcher.replaceAll(" ");
System.out.println(str);
}
}
output is:
-a1 +a2 - a3 +-a5
-a1 +a2 - a3 +-a5
the problem is I want the output to look like this:
-a1 + a2 - a3 + -a5
In this specific case, you can handle -- by just replacing them with +:
Take input as a string from the user
Remove all white space
Replace all -- with +
Continue parsing as desired
I would recommend using regular expressions and their "group" functionality. I would actually remove all whitespace to make things easier, take it out of the equation, one less thing to deal with. And obviously I would recommend simplifying the string, replacing "--" with "+", "*+" with "*" and so on.
now you can use a regex on your cleaned up string.
Pattern firstPat = Pattern.compile("(((\\+|-)?)\\d+(.\\d+)?)");//for matching the first number, leading sign is optional
Pattern remainingPat = Pattern.compile("(\\+|-)(\\d+(.\\d+)?)");//for remaining numbers, leading sign is mandatory.
Pattern remainingPatWithExtOps = Pattern.compile("(\\*|/|\\+|-)(-?\\d+(.\\d+)?)");//for remaining numbers, accommodating multiply and divide with negative signs(positive signs should have been cleaned out)
Matcher match = firstPat.matcher(inputString);
now you can iterate through the string using the match.find() method. and then use match.group(1) to get the sign/operation, and use match.group(2) to get the number...
So...
Double firstnum;
boolean firstNumSigned = false;
if(match.find())
{
firstNum = Double.parse(match.group(0));// Parsing handles possible sign in string.
//obv check for exceptions during this and double check group num
String tmp = match.group(1);
firstNumSigned = tmp.equals("+") || tmp.equals("-");
}
else
{//no match means the input was probably invalid....
throw new IllegalArgumentException("What the heck were you thinking inputting that?!");
}
match = remainingPat.matcher(inputString);//use our other pattern for remaining numbers
if(firstNumSigned)
{
match.find();//a signed first number will cause success here, we need to ignore this since we already got the first number
}
Double tmpRemaingingNum;
String operation;
while(match.find())
{
operation = match.group(1);
tmpRemainingNum = Double.parse(match.group(2));
//Do what you want with these values now until match.find() returns false and you are done
}
PS: code is not tested, im fairly confident of the regex, but I'm not 100% sure about the grouping brackets on the first pattern.. might need to experiment
Start by replacing -- with +, which is mathematically equivalent. Or start by replacing -- with - -, which would keep - and 4 together.
Check this ,
Read both strings and integers in between operators like '*,--,-,+"
We can read both integers and characters.
public static void main(String[] args) {
// TODO Auto-generated method stub
final Pattern remainingPatWithExt=Pattern.compile("(\\p{L}\\p{M}*)[\\p{L}\\p{M}0-9^\\-.-?_+-=<>!;]*");
String check = "a1+a2+--a7+ a3 +-a5";
Matcher matcher = remainingPatWithExt.matcher(check);
while( matcher.find())
{
System.out.println(matcher.group());
//use matcher.group(0) or matcher.group(1)
}
}
output
a1
a2
a7
a3
a5
Related
For my project I have to read various input graphs. Unfortunately, the input edges have not the same format. Some of them are comma-separated, others are tab-separated, etc. For example:
File 1:
123,45
67,89
...
File 2
123 45
67 89
...
Rather than handling each case separately, I would like to automatically detect the split characters. Currently I have developed the following solution:
String str = "123,45";
String splitChars = "";
for(int i=0; i < str.length(); i++) {
if(!Character.isDigit(str.charAt(i))) {
splitChars += str.charAt(i);
}
}
String[] endpoints = str.split(splitChars);
Basically I pick the first row and select all the non-numeric characters, then I use the generated substring as split characters. Is there a cleaner way to perform this?
Split requires a regexp, so your code would fail for many reasons: If the separator has meaning in regexp (say, +), it'll fail. If there is more than 1 non-digit character, your code will also fail. If you code contains more than exactly 2 numbers, it will also fail. Imagine it contains hello, world - then your splitChars string becomes " , " - and your split would do nothing (that would split the string "test , abc" into two, nothing else).
Why not make a regexp to fetch digits, and then find all sequences of digits, instead of focussing on the separators?
You're using regexps whether you want to or not, so let's make it official and use Pattern, while we are at it.
private static final Pattern ALL_DIGITS = Pattern.compile("\\d+");
// then in your split method..
Matcher m = ALL_DIGITS.matcher(str);
List<Integer> numbers = new ArrayList<Integer>();
// dont use arrays, generally. List is better.
while (m.find()) {
numbers.add(Integer.parseInt(m.group(0)));
}
//d+ is: Any number of digits.
m.find() finds the next match (so, the next block of digits), returning false if there aren't any more.
m.group(0) retrieves the entire matched string.
Split the string on \\D+ which means one or more non-digit characters.
Demo:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
// Test strings
String[] arr = { "123,45", "67,89", "125 89", "678 129" };
for (String s : arr) {
System.out.println(Arrays.toString(s.split("\\D+")));
}
}
}
Output:
[123, 45]
[67, 89]
[125, 89]
[678, 129]
Why not split with [^\d]+ (every group of nondigfit) :
for (String n : "123,456 789".split("[^\\d]+")) {
System.out.println(n);
}
Result:
123
456
789
I have a string which looks like following:
Turns 13,000,000 years old
Now i want to convert the digits to words in English, I have a function ready for that however I am finding problems to detect the original numbers (13,000,000) in this case, because it is separated by commas.
Currently I am using the following regex to detect a number in a string:
stats = stats.replace((".*\\d.*"), (NumberToWords.start(Integer.valueOf(notification_data_greet))));
But the above seems not to work, any suggestions?
You need to extract the number using a RegEx wich allows for the commas. The most robust one I can think of right now is
\d{1,3}(,?\d{3})*
Wich matches any unsigned Integer both with correctly placed commas and without commas (and weird combinations thereof like 100,000000)
Then replace all , from the match by the empty String and you can parse as usual:
Pattern p = Pattern.compile("\\d{1,3}(,?\\d{3})*"); // You can store this as static final
Matcher m = p.matcher(input);
while (m.find()) { // Go through all matches
String num = m.group().replace(",", "");
int n = Integer.parseInt(num);
// Do stuff with the number n
}
Working example:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) throws InterruptedException {
String input = "1,300,000,000";
Pattern p = Pattern.compile("\\d{1,3}(,?\\d{3})*"); // You can store this as static final
Matcher m = p.matcher(input);
while (m.find()) { // Go through all matches
String num = m.group().replace(",", "");
System.out.println(num);
int n = Integer.parseInt(num);
System.out.println(n);
}
}
}
Gives output
1300000000
1300000000
Try this regex:
[0-9][0-9]?[0-9]?([0-9][0-9][0-9](,)?)*
This matches numbers that are seperated by a comma for each 1000. So it will match
10,000,000
but not
10,1,1,1
You can do it with the help of DecimalFormat instead of a regular expression
DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance();
System.out.println(format.parse("10,000,000"));
Try the below regex to match the comma separted numbers,
\d{1,3}(,\d{3})+
Make the last part as optional to match also the numbers which aren't separated by commas,
\d{1,3}(,\d{3})*
I am new to regular expression syntax, after one whole day digging on the google, still can't find a good regex in java to extract the thing I want from a string...
for example:I have a
stringA = "-3.5 + 2 * 3 / 2"
stringB = "2 * 3 / 2 - 3.5";
the regex i used was
regex="[\\+\\-\\*\\/]", -->choose +,-,*,or / from the target;
by doing this, I am able to capture ANY signs in the string including negative sign.
However, I was to capture the negative sign(-) only when it is following by a whitespace.
That is, I want the result from
string A as [ +, *, /], these three signs and stringB as [ *, / , -]
I realized I only need to add another condition into regex for the negative sign such as
regex = "[\\+{\\-\\s}\\*\\/]" ---> I want to choose same thing but with
extra condition "-"sign has to follow by a whitespace.
the square bracket does not work like this way..Is there anyone can kindly guide my how to add another condition into the original regex? or write a new regex to qualify the need? Thank you so much in advance.
Chi, this might be the simple regex you're looking for:
[+*/]|(?<=\s)-
How does it work?
There is an alternation | in the middle, which is a way of saying "match this or match that."
On the left, the character class [+*/] matches one character that is a +, * or /
On the right, the lookbehind (?<=\s) asserts "preceded by a whitespace character", then we match a minus.
How to use it?
List<String> matchList = new ArrayList<String>();
try {
Pattern regex = Pattern.compile("[+*/]|(?<=\\s)-");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
matchList.add(regexMatcher.group());
}
} catch (PatternSyntaxException ex) {
// Syntax error in the regular expression
}
If you are interested, you may want to read up on regex lookaheads and lookbehinds.
Let me know if you have any question.
What you can do is ditch the class (the [] enclosed Pattern), use OR instead, and use a negative lookahead for your minus sign, to avoid for it to be followed by a digit:
String input0 = "2 * 3 / 2 - 3.5";
String input1 = "-3.5 + 2 * 3 / 2";
Pattern p = Pattern.compile("\\+|\\-(?!\\d)|\\*|/");
Matcher m = p.matcher(input0);
while (m.find()) {
System.out.println(m.group());
}
System.out.println();
m = p.matcher(input1);
while (m.find()) {
System.out.println(m.group());
}
Output
*
/
-
+
*
/
Yet another solution.
Maybe you want to catch the minus sign regardless of white spaces and rather depending on its meaning, i. e. a binary-minus operator and not the minus sign before the numbers.
You could have the case where you could have a binary-minus without any space at all, like in 3-5 or you could have a minus sign before the number with a space between them (which it is allowed in many programming languages, Java included). So, in order to catch your tokens properly (positive-negative-numbers and binary-operators) you can try this:
public static void main(String[] args) {
String numberPattern = "(?:-? *\\d+(?:\\.\\d+)?(?:E[+-]?\\d+)?)";
String opPattern = "[+*/-]";
Pattern tokenPattern = Pattern.compile(numberPattern + "|" + opPattern);
String stringA = "-3.5 + -2 * 3 / 2";
Matcher matcher = tokenPattern.matcher(stringA);
while(matcher.find()) {
System.out.println(matcher.group().trim());
}
}
Here you are catching operators AND ALSO operands, regardless of white spaces. If you only need the binary operators, just filter them.
Try with the string "-3.5+-2*3/2" (without spaces at all) and you'll have your tokens anyway.
Try String#replaceAll(). Its very simple pattern.
// [any digit] or [minus followed by any digit] or [decimal]
String regex = "(\\d|-\\d|\\.)";
String stringA = "-3.5 + 2 * 3 / 2";
String stringA1 = stringA.replaceAll(regex, "").trim();
System.out.println(stringA1);
String stringB = "2 * 3 / 2 - 3.5";
String stringB1 = stringB.replaceAll(regex, "").trim();
System.out.println(stringB1);
output
+ * /
* / -
Note : You can get all the operators using String#split("\\s+").
How can i scan number inserted in this form: 1.7+2.8990i in java? I imagine its possible to split the line one time with +, or -? How should i take this line as a string or sth else?
Thanks
If you wanted to use a library there is always Commons Math which lets you do stuff like this:
ComplexFormat cf = new ComplexFormat();
Complex c = cf.parse("1.110 + 2.222i");
Complex second = new Complex(2.0, 5.0);
Complex answer = c.log(); // natural logarithm.
answer = c.cos(); // cosine
answer = c.pow(second); // first raised to the power of second
ComplexFormat format = new ComplexFormat(); // default format
String s1 = format.format(c); // s1 contains "1.110 + 2.222i"
String s2 = format.format(second); // s2 contains "2.0 + 5.0i"
Here is a RegEx approach (without external library but also without ability to use a Complex Number for more than just parsing):
Pattern pattern = Pattern.compile("([+-]?\\d*\\.\\d+)([+-]?\\d*\\.\\d+)i",Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher matcher = pattern.matcher("1.7+2.8990i");
if(matcher.matches()) {
System.out.println("a:" + Float.parseFloat(matcher.group(1)));
System.out.println("b:" + Float.parseFloat(matcher.group(2)));
} else {
System.out.println("Not a complex number");
}
This approach supports positive and negative values for a and b. Now one weaknesses to this approach are it doesn't tolerate spaces around number (you could safely strip spaces from your input and not alter the equation).
I'm new to regular expressions, and was wondering how I could get only the first number in a string like 100 2011-10-20 14:28:55. In this case, I'd want it to return 100, but the number could also be shorter or longer.
I was thinking about something like [0-9]+, but it takes every single number separately (100,2001,10,...)
Thank you.
/^[^\d]*(\d+)/
This will start at the beginning, skip any non-digits, and match the first sequence of digits it finds
EDIT:
this Regex will match the first group of numbers, but, as pointed out in other answers, parseInt is a better solution if you know the number is at the beginning of the string
Try this to match for first number in string (which can be not at the beginning of the string):
String s = "2011-10-20 525 14:28:55 10";
Pattern p = Pattern.compile("(^|\\s)([0-9]+)($|\\s)");
Matcher m = p.matcher(s);
if (m.find()) {
System.out.println(m.group(2));
}
Just
([0-9]+) .*
If you always have the space after the first number, this will work
Assuming there's always a space between the first two numbers, then
preg_match('/^(\d+)/', $number_string, $matches);
$number = $matches[1]; // 100
But for something like this, you'd be better off using simple string operations:
$space_pos = strpos($number_string, ' ');
$number = substr($number_string, 0, $space_pos);
Regexs are computationally expensive, and should be avoided if possible.
the below code would do the trick.
Integer num = Integer.parseInt("100 2011-10-20 14:28:55");
[0-9] means the numbers 0-9 can be used the + means 1 or more times. if you use [0-9]{3} will get you 3 numbers
Try ^(?'num'[0-9]+).*$ which forces it to start at the beginning, read a number, store it to 'num' and consume the remainder without binding.
This string extension works perfectly, even when string not starts with number.
return 1234 in each case - "1234asdfwewf", "%sdfsr1234" "## # 1234"
public static string GetFirstNumber(this string source)
{
if (string.IsNullOrEmpty(source) == false)
{
// take non digits from string start
string notNumber = new string(source.TakeWhile(c => Char.IsDigit(c) == false).ToArray());
if (string.IsNullOrEmpty(notNumber) == false)
{
//replace non digit chars from string start
source = source.Replace(notNumber, string.Empty);
}
//take digits from string start
source = new string(source.TakeWhile(char.IsDigit).ToArray());
}
return source;
}
NOTE: In Java, when you define the patterns as string literals, do not forget to use double backslashes to define a regex escaping backslash (\. = "\\.").
To get the number that appears at the start or beginning of a string you may consider using
^[0-9]*\.?[0-9]+ # Float or integer, leading digit may be missing (e.g, .35)
^-?[0-9]*\.?[0-9]+ # Optional - before number (e.g. -.55, -100)
^[-+]?[0-9]*\.?[0-9]+ # Optional + or - before number (e.g. -3.5, +30)
See this regex demo.
If you want to also match numbers with scientific notation at the start of the string, use
^[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)? # Just number
^-?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)? # Number with an optional -
^[-+]?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)? # Number with an optional - or +
See this regex demo.
To make sure there is no other digit on the right, add a \b word boundary, or a (?!\d)
or (?!\.?\d) negative lookahead that will fail the match if there is any digit (or . and a digit) on the right.
public static void main(String []args){
Scanner s=new Scanner(System.in);
String str=s.nextLine();
Pattern p=Pattern.compile("[0-9]+");
Matcher m=p.matcher(str);
while(m.find()){
System.out.println(m.group()+" ");
}
\d+
\d stands for any decimal while + extends it to any other decimal coming directly after, until there is a non number character like a space or letter