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.
Related
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.
This question already has answers here:
What is the most elegant way to convert a hyphen separated word (e.g. "do-some-stuff") to the lower camel-case variation (e.g. "doSomeStuff")?
(11 answers)
Closed 5 years ago.
I'd like to change every word using an underscore as word without underscore but with an uppercase
Example : new_york -> newYork
so far my solution is writing a line for every letter, which is not very efficient:
mySolution = mySolution.replaceAll("_a", "A");
Edit: This question is all about using ReplaceAll in one line and has therefore nothing to do with the other question. I can manage writing a "long" program but I guess most users would be happy to get an actual answer to that question.
public class HelloWorld {
public static void main(String[] args) {
System.out.println(convert("Hello W_o_rld_"));
}
static String convert(String s) {
StringBuilder sc = new StringBuilder();
for (int i = 0; i < s.length() - 1; i++) { //to avoid _ at last index
if (s.charAt(i) == '_') {
sc.append((Character.toUpperCase(s.charAt(i + 1))));
i++;
} else {
sc.append(s.charAt(i));
}
}
return sc.toString();
}
}
Iterate through the chars of String and modify the next char after _
This question already has answers here:
Split string at hyphen characters too
(3 answers)
Closed 7 years ago.
Hey guys I am trying to split a string that is a mathematical expression.
For example - 1.1234-345+43/23.546*34
I want to split by -+/* and keep all numbers.
I have tried this:
String[] newString = "242342.4242+424-32.545".split("[+-//*]");
But it does not work, it also splits by the . and it gives me 5 numbers in the array in the end, and it should give me 3 numbers.
The new string should look like this:
newString[0] = 242342.4242
newstring[1] = 424
newString[2] = 32.545
public static void main(String[] args) {
// Using | in pattern
// \\ for special character
String[] newString = "242342.4242+424-32.545".split("\\+|-|\\*"); // +|-|*
System.out.println(Arrays.toString(newString));
// Output
// [242342.4242, 424, 32.545]
// In the real world. You need to handle Space too
// so using this pattern
// \\s*(\\+|-|\\*)\\s*
String[] newString2 = "242342.4242 + 424 - 32.545".split("\\s*(\\+|-|\\*)\\s*");
System.out.println(Arrays.toString(newString2));
// Output
// [242342.4242, 424, 32.545] - No spaces
}
public class test
{
public static void main(String[] args)
{
String[] newString = "242342.4242+424-32.545".split("[-+*/]");
for (String s : newString)
{
System.out.println(s);
}
}
}
Suppose I am given this string-
String A_Old[]="010.011.100.000.111";
On every occurrence of "000" I am expected to break the string and wrap the end towards the front of the string. The resultant should look like this-
String A_New[]="111.010.011.100";
Any help on how to tackle this problem would be appreciated.
Also, what do I do when there are multiple occurrences of "000"?
String A_Old[]="010.011.100.000.111.001.011.000.101.110";
should convert to :
String A_New[]="101.110.111.001.011.010.011.100";
Code in java or c++ is understood and appreciated.
EDIT
This was what I thought would work-
String b[]=A_Old.split(".000.",2); //should split the string in 2 parts.
A_New=b[1].concat(b[0]); // concatenation with a loss of a period
I was told to avoid the loss of the period as well as not using dummy variables. Both of which fails here. Any idea on how to tackle this?
To rotate the list, you wanna split and then concatenate in the order you want. You probably want to check for blanks/if it's the last element.
public static void main(String[] args)
{
String inString = "010.011.100.000.111";
String outString = "";
String[] arr = inString.split("\\.000\\.");
outString = arr[0];
for(int i = 1; i < arr.length; i++)
{
outString = outString + arr[i];
}
System.out.println(outString);
}
By Using Split method and reverse forloop in java
public static void main(String[] args) {
//insert code here
String A_Old="010.011.100.000.111.001.011.000.101.110";
String A_new ="";
String newe[]=A_Old.split("\\.000");
for(int i=newe.length-1;i>=0;i--){
A_new+=newe[i];
}
System.out.print(A_new.replaceFirst("\\.", ""));
}
I tried it in java:
public static String convert(String in) {
String[] strs = in.split("\\.*000\\.*");
StringBuilder sb = new StringBuilder();
for (int i = strs.length - 1; i >= 0; --i) {
sb.append(strs[i]);
if (i > 0 && strs[i - 1].length() > 0) {
sb.append(".");
}
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(convert("010.011.100.000.111"));
System.out.println(convert("010.011.100.000.111.001.011.000.101.110"));
System.out.println(convert("010.011.100.111"));
System.out.println(convert("000.010.011.100.111"));
System.out.println(convert("010.011.100.111.000"));
System.out.println(convert("000.010.011.100.111.000"));
}
Output:
111.010.011.100
101.110.111.001.011.010.011.100
010.011.100.111
010.011.100.111
010.011.100.111
010.011.100.111
"No dummy variables" sounds like a recursive solution is sought. Is this a Scheme class?
Here's a Perl solution. C++11 is sufficiently high-level to provide most of the facilities demonstrated here:
my #tests = (
'010.011.100.000.111',
'010.011.100.000.111.001.011.000.101.110'
);
foreach ( #tests ) {
print "$_ => ", rotate($_), "\n"; # Call our rotate routine, and show results.
}
sub rotate {
# Split the string into components, reverse their order, join them with '.'
return join('.', reverse split /(?:^|\.)000(?:\.|$)/, shift);
}
No dummy variables. In fact, no explicit variables either.
Here's how the split regex works:
(?:^|\.) # Match either start of string, or a dot.
000 # Match three zeros.
(?:\.|$) # Match either a dot, or the end of string.
This permits the 000 to appear anywhere in the string (including beginning or end). If it appears at the beginning, there will not need to be a leading dot. If it appears at the end, a trailing dot will not be required. Anywhere else, dots must surround the 000.
Update:
Here is a recursive solution using Perl. From what I've read of the Java solutions (I'm not a Java guy), it seems like translation should be straightforward for someone with some Java background.
my #tests = (
'010.011.100.000.111',
'010.011.100.000.111.001.011.000.101.110'
);
foreach ( #tests ) {
print "($_) => (", rotate($_), ")\n";
}
sub rotate {
my( $ok, $rest ) = split /(?:^|\.)000(?:\.|$)/, $_[0], 2;
return $ok unless defined $rest;
return join( '.', rotate($rest), $ok);
}
Update2:
And here's another Perl solution that eliminates any explicit variables, using only subroutine parameters:
my #tests = (
'010.011.100.000.111',
'010.011.100.000.111.001.011.000.101.110'
);
foreach ( #tests ) {
print "($_) => (", rotate($_), ")\n";
}
sub rotate {
return sub {
return $_[0] unless defined $_[1];
return join( '.', rotate($_[1]), $_[0]);
}->( split /(?:^|\.)000(?:\.|$)/, shift, 2 );
}
I have no idea how one would translate that Java. I suspect translation would become a little more difficult, though I'm confident there must exist a semantically equivalent C++11 solution.
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.