Apply regex conditions after certain character - java

I have a string that i want to parse into an array.
The given string has the form P[AB, AC, AD] (A1, A2, A3).
I want to store it in an array like this so that all the data after the first ( will be filtered by the regex conditions:
P[AB, AC, AD]
A1
A2
A3
This is what i came up with:
String regex = "/^(([,()]+)$";
String[] numbers = stringIn.split(regex);
My problem is that it simply does not work because the regex won't filter out the pieces, everything is stored at numbers[0].

I think this is what you were trying for:
String regex = "[ ,()]+(?=[^\\]]*$)";
String stringIn = "P[AB, AC, AD] (A1, A2, A3)";
String[] numbers = stringIn.split(regex);
for (String n : numbers)
{
System.out.println(n);
}
output:
P[AB, AC, AD]
A1
A2
A3
[ ,()]+ part tries match spaces, commas and parentheses wherever they appear, but (?=[^\\]]*$) (a positive lookahead) filters out any match before the ]. I'm assuming there's only the one set of square brackets in the string.

Thought of a less elegant, but possibly easier to follow, way of doing this:
// Split the string into two parts.
// parts[0] == "P[AB, AC, AD]"
// parts[1] == "A1, A2, A3"
String[] parts = stringIn.split(" *\\(|\\)");
// Split the second part into its components.
String[] secondParts = stringInParts[1].split(", *");
// Combine the results.
String[] numbers = new String[secondParts.length + 1];
numbers[0] = parts[0];
System.arrayCopy(secondParts, 0, numbers, 1, secondParts.length);

You need to escape the parenthesis that you want to match literally, and you don't need back-slashes around the body, and you probably want to match instead of splitting.
Pattern regex = Pattern.compile("\\(([^)]+)");
Matcher m = regex.matcher(stringIn);
if (m.find()) {
String[] numbers = m.group(1).split("[,\\s]+");
}
Finally, unlike in JavaScript and C# and Python, $ in Java does not match the end of the input. You need to use \\z instead. $ in Java matches at the end of input or just before the last linebreak if there is a linebreak at the end of the input.

Related

How to split a string and save the 2 characters that I split with?

I am trying to split a given string using the java split method while the string should be devided by two different characters (+ and -) and I am willing to save the characters inside the array aswell in the same index the string has been saven.
for example :
input : String s = "4x^2+3x-2"
output :
arr[0] = 4x^2
arr[1] = +3x
arr[2] = -2
I know how to get the + or - characters in a different index between the numbers but it is not helping me,
any suggestions please?
You can face this problem in many ways. I´m sure there are clever and fancy ways to split this expression. I will show you the simplest problem-solving process that can help you.
State the problem you need to solve, the input and output
Problem: Split a math expression into subexpressions at + and - signals
Input: 4x^2+3x-2
Output: 4x^2,+3x,-2
Create a pseudo code with some logic you might think works
Given an expression string
Create an empty list of expressions
Create a subExpression string
For each character in the expression
Check if the character is + ou - then
add the subExpression in the list and create a new empty subexpression
otherwise, append the character in the subExpression
In the end, add the left subexpression in the list
Implement the pseudo-code in the programming language of your choice
String expression = "4x^2+3x-2";
List<String> expressions = new ArrayList();
StringBuilder subExpression = new StringBuilder();
for (int i = 0; i < expression.length(); i++) {
char character = expression.charAt(i);
if (character == '-' || character == '+') {
expressions.add(subExpression.toString());
subExpression = new StringBuilder(String.valueOf(character));
} else {
subExpression.append(String.valueOf(character));
}
}
expressions.add(subExpression.toString());
System.out.println(expressions);
Output
[4x^2, +3x, -2]
You will end with one algorithm that works for your problem. You can start to improve it.
Try this code:
String s = "4x^2+3x-2";
s = s.replace("+", "#+");
s = s.replace("-", "#-");
String[] ss = s.split("#");
for (int i = 0; i < ss.length; i++) {
Log.e("XOP",ss[i]);
}
This code replaces + and - with #+ and #- respectively and then splits the string with #. That way the + and - operators are not lost in the result.
If you require # as input character then you can use any other Unicode character instead of #.
Try this one:
String s = "4x^2+3x-2";
String[] arr = s.split("[\\+-]");
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
Personally I like it better to have positive matches of patterns, especially if the split pattern itself is empty.
So for instance you could use a Pattern and Matcher like this:
Pattern p = Pattern.compile("(^|[+-])([^+-]*)");
Matcher m = p.matcher("4x^2+3x-2");
while (m.find()) {
System.out.printf("%s or %s %s%n", m.group(), m.group(1), m.group(2));
}
This matches the start of the string or a plus or minus: ^|[+-], followed by any amount of characters that are not a plus or minus: [^+-]*.
Do note that the ^ first matches the start of the string, and is then used to negate a character class when used between brackets. Regular expressions are tricky like that.
Bonus: you can also use the two groups (within the parenthesis in the pattern) to match the operators - if any.
All this is presuming that you want to use/test regular expressions; generally things like this require a parser rather than a regular expression.
A one-liner for persons thinking that this is too complex:
var expressions = Pattern.compile("^|[+-][^+-]*")
.matcher("4x^2+3x-2")
.results()
.map(r -> r.group())
.collect(Collectors.toList());

How to split a string based on parenthesis and avoiding whitespace

I'm trying to reformat a string using the str.split() on string such as
"(ABD) (DEFG) (HIJKLMN)" (has one or more spaces between)
I've tried using this RegEx (Java)
[the example string] .split("\\(|\\)")
My output keeps including the "" or " " in my array from splitting, which I don't want I would want my array to be such that
array[0] = "ABC"
array[1] = "DEFG"
etc.
I would perform two steps, use String.replaceAll(String, String) to remove the () characters. Then, split on white-space. Like,
String str = "(ABD) (DEFG) (HIJKLMN)";
System.out.println(Arrays.toString(str.replaceAll("[()]", "").split("\\W+")));
which outputs (as requested)
[ABD, DEFG, HIJKLMN]
Alternatively, you could use an ArrayList and compile a reusable Pattern to perform a grouping operation on the contents of () literals. Like,
String str = "(ABD) (DEFG) (HIJKLMN)";
Pattern p = Pattern.compile("\\((\\w+)\\)");
Matcher m = p.matcher(str);
List<String> matches = new ArrayList<>();
while (m.find()) {
matches.add(m.group(1));
}
System.out.println(matches);
which will continue to work in the face of input without white-space between ()(s) like String str = "(ABD)(DEFG)(HIJKLMN)";

Best way to split "a{b}c{d}"

I'm struggling other than brute force method to split
String str = "a{b}c{d}"
into
String[] arr;
arr[0] = "a"
arr[1] = "{b}"
arr[2] = "c"
arr[3] = "{d}"
Wondering if there's a more efficient way other out there than using indexOf and subString
Based on your current edit it looks like you want to split on place which is either
directly before {
directly after }
In that case you can use split method which supports regex (regular expression). Regex provides lookaround mechanisms like
(?=subregex) to see if we are directly before something which can be matched by subregex
(?<=subregex) to see if we are directly after something which can be matched by subregex
Also { and } are considered regex metacharacters (we can use them like {m,n} to describe amount of repetitions like a{1,3} can match a, aa, aaa but not aaaa or more) so to make it normal literal we need to escape it like \{ and \}
Last thing you need is OR operator which is represented as |.
So your code can look like:
String str = "a{b}c{d}";
String[] arr = str.split("(?=\\{)|(?<=\\})"); // split at places before "{" OR after "}"
for (String s : arr){
System.out.println(s);
}
Output:
a
{b}
c
{d}
Demo: https://ideone.com/FdUbKs
just use the String.split() method (documentation)
arr = str.split()
You may use the String.split(String delimiter) method :
String str = "a {b} c {d}";
String[] arr = str.split(" ");
System.out.println(Arrays.toString(arr)); // [a, {b], c, {d}]
Use String.split()...
String[] arr = str.split(" ");
I don't know if it's as efficient as the previous regex solutions; I'm putting a single white space before { and after } then splitting string by " ":
String str = "a{b}c{d}";
String[] split = str.replace("{"," {").replace("}","} ").split(" ");
System.out.println(Arrays.toString(split));
Desired output:
[a, {b}, c, {d}]

Problems with building this regex [1,2,3]

i have a problem to build following regex:
[1,2,3,4]
i found a work-around, but i think its ugly
String stringIds = "[1,2,3,4]";
stringIds = stringIds.replaceAll("\\[", "");
stringIds = stringIds.replaceAll("\\]", "");
String[] ids = stringIds.split("\\,");
Can someone help me please to build one regex, which i can use in the split function
Thanks for help
edit:
i want to get from this string "[1,2,3,4]" to an array with 4 entries. the entries are the 4 numbers in the string, so i need to eliminate "[","]" and ",". the "," isn't the problem.
the first and last number contains [ or ]. so i needed the fix with replaceAll. But i think if i use in split a regex for ",", i also can pass a regex which eliminates "[" "]" too. But i cant figure out, who this regex should look like.
This is almost what you're looking for:
String q = "[1,2,3,4]";
String[] x = q.split("\\[|\\]|,");
The problem is that it produces an extra element at the beginning of the array due to the leading open bracket. You may not be able to do what you want with a single regex sans shenanigans. If you know the string always begins with an open bracket, you can remove it first.
The regex itself means "(split on) any open bracket, OR any closed bracket, OR any comma."
Punctuation characters frequently have additional meanings in regular expressions. The double leading backslashes... ugh, the first backslash tells the Java String parser that the next backslash is not a special character (example: \n is a newline...) so \\ means "I want an honest to God backslash". The next backslash tells the regexp engine that the next character ([ for example) is not a special regexp character. That makes me lol.
Maybe substring [ and ] from beginning and end, then split the rest by ,
String stringIds = "[1,2,3,4]";
String[] ids = stringIds.substring(1,stringIds.length()-1).split(",");
Looks to me like you're trying to make an array (not sure where you got 'regex' from; that means something different). In this case, you want:
String[] ids = {"1","2","3","4"};
If it's specifically an array of integer numbers you want, then instead use:
int[] ids = {1,2,3,4};
Your problem is not amenable to splitting by delimiter. It is much safer and more general to split by matching the integers themselves:
static String[] nums(String in) {
final Matcher m = Pattern.compile("\\d+").matcher(in);
final List<String> l = new ArrayList<String>();
while (m.find()) l.add(m.group());
return l.toArray(new String[l.size()]);
}
public static void main(String args[]) {
System.out.println(Arrays.toString(nums("[1, 2, 3, 4]")));
}
If the first line your code is following:
String stringIds = "[1,2,3,4]";
and you're trying to iterate over all number items, then the follwing code-frag only could work:
try {
Pattern regex = Pattern.compile("\\b(\\d+)\\b", Pattern.MULTILINE);
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
for (int i = 1; i <= regexMatcher.groupCount(); i++) {
// matched text: regexMatcher.group(i)
// match start: regexMatcher.start(i)
// match end: regexMatcher.end(i)
}
}
} catch (PatternSyntaxException ex) {
// Syntax error in the regular expression
}

problem with java split()

I have a string:
strArray= "-------9---------------";
I want to find 9 from the string. The string may be like this:
strArray= "---4-5-5-7-9---------------";
Now I want to find out only the digits from the string. I need the values 9,4, or such things and ignore the '-' . I tried the following:
strArray= strignId.split("-");
but it gets error, since there are multiple '-' and I don't get my output. So what function of java should be used?
My input and output should be as follows:
input="-------9---------------";
output="9";
input="---4-5-5-7-9---------------";
output="45579";
What should I do?
The + is a regex metacharacter of "one-or-more" repetition, so the pattern -+ is "one or more dash". This would allow you to use str.split("-+") instead, but you may get an empty string as first element.
If you just want to remove all -, then you can do str = str.replace("-", ""). This uses replace(CharSequence, CharSequence) method, which performs literal String replacement, i.e. not regex patterns.
If you want a String[] with each digit in its own element, then it's easiest to do in two steps: first remove all non-digits, then use zero-length assertion to split everywhere that's not the beginning of the string (?!^) (to prevent getting an empty string as a first element). If you want a char[], then you can just call String.toCharArray()
Lastly, if the string can be very long, it's better to use a java.util.regex.Matcher in a find() loop looking for a digit \d, or a java.util.Scanner with a delimiter \D*, i.e. a sequence (possibly empty) of non-digits. This will not give you an array, but you can use the loop to populate a List (see Effective Java 2nd Edition, Item 25: Prefer lists to arrays).
References
regular-expressions.info/Repetition with Star and Plus, Character Class, Lookaround
Snippets
Here are some examples to illustrate the above ideas:
System.out.println(java.util.Arrays.toString(
"---4--5-67--8-9---".split("-+")
));
// [, 4, 5, 67, 8, 9]
// note the empty string as first element
System.out.println(
"---4--5-67--8-9---".replace("-", "")
);
// 456789
System.out.println(java.util.Arrays.toString(
"abcdefg".toCharArray()
));
// [a, b, c, d, e, f, g]
The next example first deletes all non-digit \D, then splitting everywhere except the beginning of the string (?!^), to get a String[] each containing a digit:
System.out.println(java.util.Arrays.toString(
"#*#^$4#!#5ajs67>?<{8_(9SKJDH"
.replaceAll("\\D", "")
.split("(?!^)")
));
// [4, 5, 6, 7, 8, 9]
This uses a Scanner, with \D* as delimiter, to get each digit as its own token, using it to populate a List<String>:
List<String> digits = new ArrayList<String>();
String text = "(&*!##123ask45{P:L6";
Scanner sc = new Scanner(text).useDelimiter("\\D*");
while (sc.hasNext()) {
digits.add(sc.next());
}
System.out.println(digits);
// [1, 2, 3, 4, 5, 6]
Common problems with split()
Here are some common beginner problems when dealing with String.split:
Lesson #1: split takes a regular expression pattern
This is probably the most common beginner mistake:
System.out.println(java.util.Arrays.toString(
"one|two|three".split("|")
));
// [, o, n, e, |, t, w, o, |, t, h, r, e, e]
System.out.println(java.util.Arrays.toString(
"not.like.this".split(".")
));
// []
The problem here is that | and . are regex metacharacters, and since they are intended to be matched literally, they need to be escaped by preceding with a backslash, which as a Java string literal is "\\".
System.out.println(java.util.Arrays.toString(
"one|two|three".split("\\|")
));
// [one, two, three]
System.out.println(java.util.Arrays.toString(
"not.like.this".split("\\.")
));
// [not, like, this]
Lesson #2: split discards trailing empty strings by default
Sometimes it's desired to keep trailing empty strings (which are discarded by default split):
System.out.println(java.util.Arrays.toString(
"a;b;;d;;;g;;".split(";")
));
// [a, b, , d, , , g]
Note that there are slots for the "missing" values for c, e, f, but not for h and i. To fix this, you can use a negative limit argument to String.split(String regex, int limit).
System.out.println(java.util.Arrays.toString(
"a;b;;d;;;g;;".split(";", -1)
));
// [a, b, , d, , , g, , ]
You can also use a positive limit of n to apply the pattern at most n - 1 times (i.e. resulting in no more than n elements in the array).
Zero-width matching split examples
Here are more examples of splitting on zero-width matching constructs; this can be used to split a string but also keep "delimiters".
Simple sentence splitting, keeping punctuation marks:
String str = "Really?Wow!This.Is.Awesome!";
System.out.println(java.util.Arrays.toString(
str.split("(?<=[.!?])")
)); // prints "[Really?, Wow!, This., Is., Awesome!]"
Splitting a long string into fixed-length parts, using \G
String str = "012345678901234567890";
System.out.println(java.util.Arrays.toString(
str.split("(?<=\\G.{4})")
)); // prints "[0123, 4567, 8901, 2345, 6789, 0]"
Split before capital letters (except the first!)
System.out.println(java.util.Arrays.toString(
"OhMyGod".split("(?=(?!^)[A-Z])")
)); // prints "[Oh, My, God]"
A variety of examples is provided in related questions below.
References
regular-expressions.info/Lookarounds
Related questions
Can you use zero-width matching regex in String split?
"abc<def>ghi<x><x>" -> "abc", "<def>", "ghi", "<x>", "<x>"
How do I convert CamelCase into human-readable names in Java?
"AnXMLAndXSLT2.0Tool" -> "An XML And XSLT 2.0 Tool"
C# version: is there a elegant way to parse a word and add spaces before capital letters
Java split is eating my characters
Is there a way to split strings with String.split() and include the delimiters?
Regex split string but keep separators
You don't use split!
Split is to get the things BETWEEN the separator.
For this you want to eliminate the unwanted chars; '-'
The solution is simple
out=in.replaceAll("-","");
Use something like this to get the single values splitted. I'd rather eliminate the unwanted chars first to avoid getting empty/null String in the result array.
final Vector nodes = new Vector();
int index = original.indexOf(separator);
while (index >= 0) {
nodes.addElement(original.substring(0, index));
original = original.substring(index + separator.length());
index = original.indexOf(separator);
}
nodes.addElement(original);
final String[] result = new String[nodes.size()];
if (nodes.size() > 0) {
for (int loop = 0; loop smaller nodes.size(); loop++) {
result[loop] = (String) nodes.elementAt(loop);
}
}
return result;
}

Categories

Resources